summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorcvs2svn Import User <samba-bugs@samba.org>2002-08-17 07:09:23 +0000
committercvs2svn Import User <samba-bugs@samba.org>2002-08-17 07:09:23 +0000
commit592dd249579511f7ce863a42030d9a51ca026c27 (patch)
tree805985e633b375fd0a88a564a35c38410093a1dd /source3/lib
parent08663f11ed5bc05ff352bda74774d5e7045da1e5 (diff)
parent8690b271a6a4feb112e0a6c03fe99ee25f86430b (diff)
downloadsamba-592dd249579511f7ce863a42030d9a51ca026c27.tar.gz
samba-592dd249579511f7ce863a42030d9a51ca026c27.tar.bz2
samba-592dd249579511f7ce863a42030d9a51ca026c27.zip
This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to be commit 6938b5b98abd9ba055a46583a05c4fc07e32f529)
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/adt_tree.c464
-rw-r--r--source3/lib/popt_common.c49
-rw-r--r--source3/lib/system_smbd.c105
-rw-r--r--source3/lib/util_smbd.c65
-rw-r--r--source3/lib/util_uuid.c72
5 files changed, 755 insertions, 0 deletions
diff --git a/source3/lib/adt_tree.c b/source3/lib/adt_tree.c
new file mode 100644
index 0000000000..2c18bb1198
--- /dev/null
+++ b/source3/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; i<root->num_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; i<node->num_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 /<key1>/<key2>/...
+ */
+
+ 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, 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; i<num_children; i++ )
+ sorted_tree_print_children( node->children[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; i<num_children; i++ ) {
+ sorted_tree_print_children( tree->root->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/source3/lib/popt_common.c b/source3/lib/popt_common.c
new file mode 100644
index 0000000000..a3d6af4fbc
--- /dev/null
+++ b/source3/lib/popt_common.c
@@ -0,0 +1,49 @@
+/*
+ Unix SMB/CIFS implementation.
+ Common popt routines
+
+ Copyright (C) Tim Potter 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"
+
+/* Handle -d,--debuglevel command line option */
+
+static void debug_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg, const void *data)
+{
+ extern BOOL AllowDebugChange;
+
+ switch(opt->val) {
+ case 'd':
+ if (arg) {
+ DEBUGLEVEL = atoi(arg);
+ AllowDebugChange = False;
+ }
+
+ break;
+ }
+}
+
+struct poptOption popt_common_debug[] = {
+ { NULL, 0, POPT_ARG_CALLBACK, debug_callback },
+ { "debuglevel", 'd', POPT_ARG_INT, NULL, 'd', "Set debug level",
+ "DEBUGLEVEL" },
+ { 0 }
+};
diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c
new file mode 100644
index 0000000000..28ceaf3939
--- /dev/null
+++ b/source3/lib/system_smbd.c
@@ -0,0 +1,105 @@
+/*
+ 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;
+
+ /* 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) {
+ free(gids_saved);
+ /* very strange! */
+ return -1;
+ }
+
+ if (initgroups(user, gid) != 0) {
+ 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);
+
+ ret = getgroups(*grpcnt, groups);
+ if (ret >= 0) {
+ *grpcnt = ret;
+ }
+
+ 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();
+#endif
+}
diff --git a/source3/lib/util_smbd.c b/source3/lib/util_smbd.c
new file mode 100644
index 0000000000..071f20b416
--- /dev/null
+++ b/source3/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/source3/lib/util_uuid.c b/source3/lib/util_uuid.c
new file mode 100644
index 0000000000..63e2504982
--- /dev/null
+++ b/source3/lib/util_uuid.c
@@ -0,0 +1,72 @@
+/*
+ * 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;
+ uint16 clock_seq;
+ 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);
+ SSVAL(out, 8, uu->clock_seq);
+ 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);
+ uu->clock_seq = SVAL(ptr, 8);
+ 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 = (uu.clock_seq & 0x3FFF) | 0x8000;
+ uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
+ uuid_pack(&uu, out);
+}