~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source3/lib/adt_tree.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include "includes.h"
21
21
#include "adt_tree.h"
22
22
 
 
23
struct tree_node {
 
24
        struct tree_node        *parent;
 
25
        struct tree_node        **children;
 
26
        int                     num_children;
 
27
        char                    *key;
 
28
        void                    *data_p;
 
29
};
 
30
 
 
31
struct sorted_tree {
 
32
        struct tree_node *root;
 
33
};
23
34
 
24
35
/**************************************************************************
25
36
 *************************************************************************/
27
38
static bool trim_tree_keypath( char *path, char **base, char **new_path )
28
39
{
29
40
        char *p;
30
 
        
 
41
 
31
42
        *new_path = *base = NULL;
32
 
        
 
43
 
33
44
        if ( !path )
34
45
                return False;
35
 
        
 
46
 
36
47
        *base = path;
37
 
        
38
 
        p = strchr( path, '/' );
39
 
        
 
48
 
 
49
        p = strchr( path, '\\' );
 
50
 
40
51
        if ( p ) {
41
52
                *p = '\0';
42
53
                *new_path = p+1;
43
54
        }
44
 
        
 
55
 
45
56
        return True;
46
57
}
47
58
 
48
 
 
49
59
/**************************************************************************
50
 
 Initialize the tree's root.  The cmp_fn is a callback function used
51
 
 for comparision of two children
 
60
 Initialize the tree's root.
52
61
 *************************************************************************/
53
62
 
54
 
 SORTED_TREE* pathtree_init( void *data_p, int (cmp_fn)(void*, void*) )
 
63
struct sorted_tree *pathtree_init(void *data_p)
55
64
{
56
 
        SORTED_TREE *tree = NULL;
57
 
        
58
 
        if ( !(tree = TALLOC_ZERO_P(NULL, SORTED_TREE)) )
 
65
        struct sorted_tree *tree = NULL;
 
66
 
 
67
        tree = talloc_zero(NULL, struct sorted_tree);
 
68
        if (tree == NULL) {
59
69
                return NULL;
60
 
                
61
 
        tree->compare = cmp_fn;
62
 
        
63
 
        if ( !(tree->root = TALLOC_ZERO_P(tree, TREE_NODE)) ) {
 
70
        }
 
71
 
 
72
        tree->root = talloc_zero(tree, struct tree_node);
 
73
        if (tree->root == NULL) {
64
74
                TALLOC_FREE( tree );
65
75
                return NULL;
66
76
        }
67
 
        
 
77
 
68
78
        tree->root->data_p = data_p;
69
 
        
 
79
 
70
80
        return tree;
71
81
}
72
82
 
75
85
 Find the next child given a key string
76
86
 *************************************************************************/
77
87
 
78
 
static TREE_NODE* pathtree_birth_child( TREE_NODE *node, char* key )
 
88
static struct tree_node *pathtree_birth_child(struct tree_node *node,
 
89
                                              char* key )
79
90
{
80
 
        TREE_NODE *infant = NULL;
81
 
        TREE_NODE **siblings;
 
91
        struct tree_node *infant = NULL;
 
92
        struct tree_node **siblings;
82
93
        int i;
83
 
        
84
 
        if ( !(infant = TALLOC_ZERO_P( node, TREE_NODE)) )
 
94
 
 
95
        infant = talloc_zero(node, struct tree_node);
 
96
        if (infant == NULL) {
85
97
                return NULL;
86
 
        
 
98
        }
 
99
 
87
100
        infant->key = talloc_strdup( infant, key );
88
101
        infant->parent = node;
89
 
        
90
 
        siblings = TALLOC_REALLOC_ARRAY( node, node->children, TREE_NODE *, node->num_children+1 );
91
 
        
 
102
 
 
103
        siblings = talloc_realloc(node, node->children, struct tree_node *,
 
104
                                  node->num_children+1);
 
105
 
92
106
        if ( siblings )
93
107
                node->children = siblings;
94
 
        
 
108
 
95
109
        node->num_children++;
96
 
        
 
110
 
97
111
        /* first child */
98
 
        
 
112
 
99
113
        if ( node->num_children == 1 ) {
100
114
                DEBUG(11,("pathtree_birth_child: First child of node [%s]! [%s]\n", 
101
115
                        node->key ? node->key : "NULL", infant->key ));
111
125
                 * Insert the new infanct in ascending order 
112
126
                 * from left to right
113
127
                 */
114
 
        
 
128
 
115
129
                for ( i = node->num_children-1; i>=1; i-- )
116
130
                {
117
131
                        DEBUG(11,("pathtree_birth_child: Looking for crib; infant -> [%s], child -> [%s]\n",
118
132
                                infant->key, node->children[i-1]->key));
119
 
                        
 
133
 
120
134
                        /* the strings should never match assuming that we 
121
135
                           have called pathtree_find_child() first */
122
 
                
 
136
 
123
137
                        if ( StrCaseCmp( infant->key, node->children[i-1]->key ) > 0 ) {
124
138
                                DEBUG(11,("pathtree_birth_child: storing infant in i == [%d]\n", 
125
139
                                        i));
126
140
                                node->children[i] = infant;
127
141
                                break;
128
142
                        }
129
 
                        
 
143
 
130
144
                        /* bump everything towards the end on slot */
131
 
                        
 
145
 
132
146
                        node->children[i] = node->children[i-1];
133
147
                }
134
148
 
135
149
                DEBUG(11,("pathtree_birth_child: Exiting loop (i == [%d])\n", i ));
136
 
                
 
150
 
137
151
                /* if we haven't found the correct slot yet, the child 
138
152
                   will be first in the list */
139
 
                   
 
153
 
140
154
                if ( i == 0 )
141
155
                        node->children[0] = infant;
142
156
        }
148
162
 Find the next child given a key string
149
163
 *************************************************************************/
150
164
 
151
 
static TREE_NODE* pathtree_find_child( TREE_NODE *node, char* key )
 
165
static struct tree_node *pathtree_find_child(struct tree_node *node,
 
166
                                             char *key )
152
167
{
153
 
        TREE_NODE *next = NULL;
 
168
        struct tree_node *next = NULL;
154
169
        int i, result;
155
 
        
 
170
 
156
171
        if ( !node ) {
157
172
                DEBUG(0,("pathtree_find_child: NULL node passed into function!\n"));
158
173
                return NULL;
159
174
        }
160
 
        
 
175
 
161
176
        if ( !key ) {
162
177
                DEBUG(0,("pathtree_find_child: NULL key string passed into function!\n"));
163
178
                return NULL;
164
179
        }
165
 
        
 
180
 
166
181
        for ( i=0; i<node->num_children; i++ )
167
182
        {       
168
183
                DEBUG(11,("pathtree_find_child: child key => [%s]\n",
169
184
                        node->children[i]->key));
170
 
                        
 
185
 
171
186
                result = StrCaseCmp( node->children[i]->key, key );
172
 
                
 
187
 
173
188
                if ( result == 0 )
174
189
                        next = node->children[i];
175
 
                
 
190
 
176
191
                /* if result > 0 then we've gone to far because
177
192
                   the list of children is sorted by key name 
178
193
                   If result == 0, then we have a match         */
179
 
                   
 
194
 
180
195
                if ( result > 0 )
181
196
                        break;
182
197
        }
183
198
 
184
199
        DEBUG(11,("pathtree_find_child: %s [%s]\n",
185
200
                next ? "Found" : "Did not find", key ));        
186
 
        
 
201
 
187
202
        return next;
188
203
}
189
204
 
191
206
 Add a new node into the tree given a key path and a blob of data
192
207
 *************************************************************************/
193
208
 
194
 
 WERROR pathtree_add( SORTED_TREE *tree, const char *path, void *data_p )
 
209
WERROR pathtree_add(struct sorted_tree *tree, const char *path, void *data_p)
195
210
{
196
211
        char *str, *base, *path2;
197
 
        TREE_NODE *current, *next;
 
212
        struct tree_node *current, *next;
198
213
        WERROR ret = WERR_OK;
199
 
        
 
214
 
200
215
        DEBUG(8,("pathtree_add: Enter\n"));
201
 
                
202
 
        if ( !path || *path != '/' ) {
 
216
 
 
217
        if ( !path || *path != '\\' ) {
203
218
                DEBUG(0,("pathtree_add: Attempt to add a node with a bad path [%s]\n",
204
219
                        path ? path : "NULL" ));
205
220
                return WERR_INVALID_PARAM;
206
221
        }
207
 
        
 
222
 
208
223
        if ( !tree ) {
209
224
                DEBUG(0,("pathtree_add: Attempt to add a node to an uninitialized tree!\n"));
210
225
                return WERR_INVALID_PARAM;
211
226
        }
212
 
        
213
 
        /* move past the first '/' */
214
 
        
 
227
 
 
228
        /* move past the first '\\' */
 
229
 
215
230
        path++; 
216
231
        path2 = SMB_STRDUP( path );
217
232
        if ( !path2 ) {
218
233
                DEBUG(0,("pathtree_add: strdup() failed on string [%s]!?!?!\n", path));
219
234
                return WERR_NOMEM;
220
235
        }
221
 
        
 
236
 
222
237
 
223
238
        /* 
224
239
         * this works sort of like a 'mkdir -p' call, possibly 
225
240
         * creating an entire path to the new node at once
226
241
         * The path should be of the form /<key1>/<key2>/...
227
242
         */
228
 
        
 
243
 
229
244
        base = path2;
230
245
        str  = path2;
231
246
        current = tree->root;
232
 
        
 
247
 
233
248
        do {
234
249
                /* break off the remaining part of the path */
235
 
                
236
 
                str = strchr( str, '/' );
 
250
 
 
251
                str = strchr( str, '\\' );
237
252
                if ( str )
238
253
                        *str = '\0';
239
 
                        
 
254
 
240
255
                /* iterate to the next child--birth it if necessary */
241
 
                
 
256
 
242
257
                next = pathtree_find_child( current, base );
243
258
                if ( !next ) {
244
259
                        next = pathtree_birth_child( current, base );
249
264
                        }
250
265
                }
251
266
                current = next;
252
 
                
 
267
 
253
268
                /* setup the next part of the path */
254
 
                
 
269
 
255
270
                base = str;
256
271
                if ( base ) {
257
 
                        *base = '/';
 
272
                        *base = '\\';
258
273
                        base++;
259
274
                        str = base;
260
275
                }
261
 
        
 
276
 
262
277
        } while ( base != NULL );
263
 
        
 
278
 
264
279
        current->data_p = data_p;
265
 
        
 
280
 
266
281
        DEBUG(10,("pathtree_add: Successfully added node [%s] to tree\n",
267
282
                path ));
268
283
 
275
290
 
276
291
 
277
292
/**************************************************************************
278
 
 Recursive routine to print out all children of a TREE_NODE
 
293
 Recursive routine to print out all children of a struct tree_node
279
294
 *************************************************************************/
280
295
 
281
296
static void pathtree_print_children(TALLOC_CTX *ctx,
282
 
                                TREE_NODE *node,
 
297
                                struct tree_node *node,
283
298
                                int debug,
284
299
                                const char *path )
285
300
{
319
334
 Dump the kys for a tree to the log file
320
335
 *************************************************************************/
321
336
 
322
 
 void pathtree_print_keys( SORTED_TREE *tree, int debug )
 
337
void pathtree_print_keys(struct sorted_tree *tree, int debug )
323
338
{
324
339
        int i;
325
340
        int num_children = tree->root->num_children;
343
358
 the tree
344
359
 *************************************************************************/
345
360
 
346
 
 void* pathtree_find( SORTED_TREE *tree, char *key )
 
361
void* pathtree_find(struct sorted_tree *tree, char *key )
347
362
{
348
363
        char *keystr, *base = NULL, *str = NULL, *p;
349
 
        TREE_NODE *current;
 
364
        struct tree_node *current;
350
365
        void *result = NULL;
351
 
        
 
366
 
352
367
        DEBUG(10,("pathtree_find: Enter [%s]\n", key ? key : "NULL" ));
353
368
 
354
369
        /* sanity checks first */
355
 
        
 
370
 
356
371
        if ( !key ) {
357
372
                DEBUG(0,("pathtree_find: Attempt to search tree using NULL search string!\n"));
358
373
                return NULL;
359
374
        }
360
 
        
 
375
 
361
376
        if ( !tree ) {
362
377
                DEBUG(0,("pathtree_find: Attempt to search an uninitialized tree using string [%s]!\n",
363
378
                        key ? key : "NULL" ));
364
379
                return NULL;
365
380
        }
366
 
        
 
381
 
367
382
        if ( !tree->root )
368
383
                return NULL;
369
 
        
 
384
 
370
385
        /* make a copy to play with */
371
 
        
372
 
        if ( *key == '/' )
 
386
 
 
387
        if ( *key == '\\' )
373
388
                keystr = SMB_STRDUP( key+1 );
374
389
        else
375
390
                keystr = SMB_STRDUP( key );
376
 
        
 
391
 
377
392
        if ( !keystr ) {
378
393
                DEBUG(0,("pathtree_find: strdup() failed on string [%s]!?!?!\n", key));
379
394
                return NULL;
380
395
        }
381
396
 
382
397
        /* start breaking the path apart */
383
 
        
 
398
 
384
399
        p = keystr;
385
400
        current = tree->root;
386
 
        
 
401
 
387
402
        if ( tree->root->data_p )
388
403
                result = tree->root->data_p;
389
 
                
 
404
 
390
405
        do
391
406
        {
392
407
                /* break off the remaining part of the path */
393
408
 
394
409
                trim_tree_keypath( p, &base, &str );
395
 
                        
 
410
 
396
411
                DEBUG(11,("pathtree_find: [loop] base => [%s], new_path => [%s]\n", 
397
412
                        base ? base : "",
398
413
                        str ? str : ""));
399
414
 
400
415
                /* iterate to the next child */
401
 
                
 
416
 
402
417
                current = pathtree_find_child( current, base );
403
 
        
 
418
 
404
419
                /* 
405
420
                 * the idea is that the data_p for a parent should 
406
421
                 * be inherited by all children, but allow it to be 
407
422
                 * overridden farther down
408
423
                 */
409
 
                
 
424
 
410
425
                if ( current && current->data_p )
411
426
                        result = current->data_p;
412
427
 
413
428
                /* reset the path pointer 'p' to the remaining part of the key string */
414
429
 
415
430
                p = str;
416
 
           
 
431
 
417
432
        } while ( str && current );
418
 
        
 
433
 
419
434
        /* result should be the data_p from the lowest match node in the tree */
420
435
        if ( result )
421
436
                DEBUG(11,("pathtree_find: Found data_p!\n"));
422
 
        
 
437
 
423
438
        SAFE_FREE( keystr );
424
 
        
 
439
 
425
440
        DEBUG(10,("pathtree_find: Exit\n"));
426
 
        
 
441
 
427
442
        return result;
428
443
}
429
444