r9472: Add read-only version of Samba3 registry database (doesn't compile yet)
[samba.git] / source4 / lib / samba3 / registry.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *  Copyright (C) Jelmer Vernooij                   2005
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 /* Implementation of internal registry database functions. */
23
24 #include "includes.h"
25
26 #define VALUE_PREFIX    "SAMBA_REGVAL"
27 #define REGVER_V1       1       /* first db version with write support */
28         
29 /***********************************************************************
30  Open the registry database
31  ***********************************************************************/
32  
33 static TDB_CONTEXT *samba3_open_registry ( const char *fn )
34 {
35         uint32_t vers_id;
36
37         /* placeholder tdb; reinit upon startup */
38         
39         if ( !(tdb = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0600)) )
40         {
41                 return NULL;
42         }
43
44         vers_id = tdb_fetch_int32(tdb, "INFO/version");
45         
46         if (vers_id > REGVER_V1) 
47                 return NULL;
48
49         return True;
50 }
51
52 /***********************************************************************
53  Retrieve an array of strings containing subkeys.  Memory should be 
54  released by the caller.  
55  ***********************************************************************/
56
57 int regdb_fetch_keys( TDB_CONTEXT *tdb, const char* key, REGSUBKEY_CTR *ctr )
58 {
59         char *path;
60         uint32_t num_items;
61         TDB_DATA dbuf;
62         char *buf;
63         uint32_t buflen, len;
64         int i;
65         fstring subkeyname;
66
67         DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL"));
68         
69         path = talloc_strdup(key);
70         
71         /* convert to key format */
72         for ( i = 0; path[i]; i++) {
73                 if ( path[i] == '\\' )
74                         path[i] = '/';
75         }
76         strupper_m( path );
77         
78         dbuf = tdb_fetch_bystring( tdb, path );
79         
80         buf = dbuf.dptr;
81         buflen = dbuf.dsize;
82         
83         if ( !buf ) {
84                 DEBUG(5,("regdb_fetch_keys: tdb lookup failed to locate key [%s]\n", key));
85                 return -1;
86         }
87         
88         len = tdb_unpack( buf, buflen, "d", &num_items);
89         
90         for (i=0; i<num_items; i++) {
91                 len += tdb_unpack( buf+len, buflen-len, "f", subkeyname );
92                 regsubkey_ctr_addkey( ctr, subkeyname );
93         }
94
95         SAFE_FREE( dbuf.dptr );
96         
97         DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items));
98         
99         return num_items;
100 }
101
102 /****************************************************************************
103  Unpack a list of registry values frem the TDB
104  ***************************************************************************/
105  
106 static int regdb_unpack_values(REGVAL_CTR *values, char *buf, int buflen)
107 {
108         int             len = 0;
109         uint32_t        type;
110         char            *valuename;
111         uint32_t        size;
112         uint8_t         *data_p;
113         uint32_t        num_values = 0;
114         int             i;
115         
116         /* loop and unpack the rest of the registry values */
117         
118         len += tdb_unpack(buf+len, buflen-len, "d", &num_values);
119         
120         for ( i=0; i<num_values; i++ ) {
121                 /* unpack the next regval */
122                 
123                 type = REG_NONE;
124                 size = 0;
125                 data_p = NULL;
126                 len += tdb_unpack(buf+len, buflen-len, "fdB",
127                                   valuename,
128                                   &type,
129                                   &size,
130                                   &data_p);
131                                 
132                 /* add the new value. Paranoid protective code -- make sure data_p is valid */
133
134                 if ( size && data_p ) {
135                         regval_ctr_addvalue( values, valuename, type, (const char *)data_p, size );
136                         SAFE_FREE(data_p); /* 'B' option to tdb_unpack does a malloc() */
137                 }
138
139                 DEBUG(8,("specific: [%s], len: %d\n", valuename, size));
140         }
141
142         return len;
143 }
144
145 /***********************************************************************
146  Retrieve an array of strings containing subkeys.  Memory should be 
147  released by the caller.
148  ***********************************************************************/
149
150 int regdb_fetch_values( TDB_CONTEXT *tdb, const char* key, REGVAL_CTR *values )
151 {
152         TDB_DATA data;
153         pstring keystr;
154
155         DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key));
156         
157         pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key );
158         normalize_reg_path( keystr );
159         
160         data = tdb_fetch_bystring( tdb, keystr );
161         
162         if ( !data.dptr ) {
163                 /* all keys have zero values by default */
164                 return 0;
165         }
166         
167         regdb_unpack_values( values, data.dptr, data.dsize );
168         
169         SAFE_FREE( data.dptr );
170         
171         return regval_ctr_numvals(values);
172 }