1 | #include <stdio.h> |
---|
2 | #include <stdlib.h> |
---|
3 | #include <string.h> |
---|
4 | /* #include <malloc.h> */ |
---|
5 | |
---|
6 | #include <sys/types.h> |
---|
7 | #include <netinet/in.h> /* hton ntoh */ |
---|
8 | |
---|
9 | #include "adlocal.h" |
---|
10 | /*#include "arbdb.h"*/ |
---|
11 | #include "arbdbt.h" |
---|
12 | |
---|
13 | static GB_CSTR gb_read_dict_data(GBDATA *gb_dict, long *size) { |
---|
14 | GB_CSTR data = 0; |
---|
15 | if (gb_dict->flags.compressed_data) { |
---|
16 | GB_internal_error("Dictionary is compressed"); |
---|
17 | data = GB_read_bytes(gb_dict); |
---|
18 | } |
---|
19 | else { |
---|
20 | data = GB_read_bytes_pntr(gb_dict); |
---|
21 | } |
---|
22 | *size = GB_read_bytes_count(gb_dict); |
---|
23 | return data; |
---|
24 | } |
---|
25 | |
---|
26 | GB_ERROR gb_load_dictionary_data(GBDATA *gb_main,const char *key, char **dict_data, long *size) { |
---|
27 | /* returns dictionary data (like saved in DB) |
---|
28 | * in a block allocated by gbm_get_mem(.., GBM_DICT_INDEX) |
---|
29 | */ |
---|
30 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
---|
31 | GB_ERROR error = 0; |
---|
32 | |
---|
33 | *dict_data = 0; |
---|
34 | *size = -1; |
---|
35 | gb_main = (GBDATA *)Main->data; |
---|
36 | |
---|
37 | if (key[0] == '@') { |
---|
38 | error = GB_export_error("No dictionaries for system fields"); |
---|
39 | } |
---|
40 | else { |
---|
41 | GBDATA *gb_key_data = Main->gb_key_data; |
---|
42 | GBDATA *gb_name; |
---|
43 | |
---|
44 | GB_push_my_security(gb_main); |
---|
45 | gb_name = GB_find_string(gb_key_data,"@name",key,GB_MIND_CASE,down_2_level); |
---|
46 | |
---|
47 | if (gb_name){ |
---|
48 | GBDATA *gb_key = GB_get_father(gb_name); |
---|
49 | GBDATA *gb_dict = GB_entry(gb_key,"@dictionary"); |
---|
50 | if (gb_dict) { |
---|
51 | const char *data = gb_read_dict_data(gb_dict, size); |
---|
52 | char *copy = gbm_get_mem(*size, GBM_DICT_INDEX); |
---|
53 | memcpy(copy, data, *size); |
---|
54 | *dict_data = copy; |
---|
55 | } |
---|
56 | } |
---|
57 | GB_pop_my_security(gb_main); |
---|
58 | } |
---|
59 | return error; |
---|
60 | } |
---|
61 | |
---|
62 | GB_DICTIONARY *gb_create_dict(GBDATA *gb_dict){ |
---|
63 | GB_DICTIONARY *dict = (GB_DICTIONARY *)GB_calloc(sizeof(GB_DICTIONARY),1); |
---|
64 | const char *data; |
---|
65 | GB_NINT *idata; |
---|
66 | long size; |
---|
67 | |
---|
68 | data = gb_read_dict_data(gb_dict, &size); |
---|
69 | GB_write_security_write(gb_dict,7); |
---|
70 | |
---|
71 | idata = (GB_NINT *)data; |
---|
72 | dict->words = ntohl(*idata++); |
---|
73 | dict->textlen = (int)(size - sizeof(GB_NINT)*(1+dict->words*2)); |
---|
74 | |
---|
75 | dict->offsets = idata; |
---|
76 | dict->resort = idata+dict->words; |
---|
77 | dict->text = (unsigned char*)(idata+2*dict->words); |
---|
78 | |
---|
79 | return dict; |
---|
80 | } |
---|
81 | |
---|
82 | void delete_gb_dictionary(GB_DICTIONARY *dict){ |
---|
83 | free(dict); |
---|
84 | } |
---|
85 | |
---|
86 | void gb_system_key_changed_cb(GBDATA *gbd,int *cl, GB_CB_TYPE type){ |
---|
87 | GBQUARK q = (GBQUARK)(long) cl; |
---|
88 | |
---|
89 | if (type == GB_CB_DELETE){ |
---|
90 | GB_MAIN_TYPE *Main = gb_get_main_during_cb(); |
---|
91 | |
---|
92 | delete_gb_dictionary(Main->keys[q].dictionary); |
---|
93 | Main->keys[q].dictionary = 0; |
---|
94 | Main->keys[q].gb_key = 0; |
---|
95 | }else{ |
---|
96 | gb_load_single_key_data(gbd,q); |
---|
97 | } |
---|
98 | } |
---|
99 | |
---|
100 | void gb_system_master_changed_cb(GBDATA *gbd,int *cl, GB_CB_TYPE type){ |
---|
101 | GBQUARK q = (GBQUARK)(long) cl; |
---|
102 | if (type == GB_CB_DELETE){ |
---|
103 | GB_MAIN_TYPE *Main = gb_get_main_during_cb(); |
---|
104 | Main->keys[q].gb_master_ali = 0; |
---|
105 | } |
---|
106 | else { |
---|
107 | gb_load_single_key_data(gbd,q); |
---|
108 | } |
---|
109 | } |
---|
110 | |
---|
111 | void gb_load_single_key_data(GBDATA *gb_main, GBQUARK q) { |
---|
112 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
---|
113 | struct gb_key_struct *ks = &Main->keys[q]; |
---|
114 | const char *key = ks->key; |
---|
115 | |
---|
116 | if (!Main->gb_key_data){ |
---|
117 | ks->compression_mask = -1; |
---|
118 | return; |
---|
119 | } |
---|
120 | |
---|
121 | gb_main = (GBDATA *)Main->data; |
---|
122 | if (key[0] == '@'){ |
---|
123 | ks->compression_mask = 0; |
---|
124 | ks->dictionary = 0; |
---|
125 | ks->gb_key_disabled = 1; |
---|
126 | ks->gb_master_ali = 0; |
---|
127 | } |
---|
128 | else { |
---|
129 | GBDATA *gb_key_data = Main->gb_key_data; |
---|
130 | GBDATA *gb_key,*gb_name,*gb_dict; |
---|
131 | GB_push_my_security(gb_main); |
---|
132 | gb_name = GB_find_string(gb_key_data,"@name",key,GB_MIND_CASE,down_2_level); |
---|
133 | if (gb_name){ |
---|
134 | gb_key= GB_get_father(gb_name); |
---|
135 | }else{ |
---|
136 | gb_key = gb_create_container(gb_key_data,"@key"); |
---|
137 | gb_name = gb_create(gb_key,"@name",GB_STRING); |
---|
138 | GB_write_string(gb_name,key); |
---|
139 | } |
---|
140 | |
---|
141 | GB_ensure_callback(gb_key,(GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE),gb_system_key_changed_cb,(int *)q); |
---|
142 | |
---|
143 | if (ks->dictionary) { |
---|
144 | delete_gb_dictionary(ks->dictionary); |
---|
145 | ks->dictionary = 0; |
---|
146 | } |
---|
147 | |
---|
148 | ks->compression_mask = *GBT_readOrCreate_int(gb_key,"compression_mask",-1); |
---|
149 | gb_dict = GB_entry(gb_key,"@dictionary"); |
---|
150 | ks->dictionary = gb_dict ? gb_create_dict(gb_dict) : 0; |
---|
151 | ks->gb_key = gb_key; |
---|
152 | |
---|
153 | { |
---|
154 | char buffer[256]; |
---|
155 | memset(buffer,0,256); |
---|
156 | sprintf(buffer,"%s/@master_data/@%s",GB_SYSTEM_FOLDER,key); |
---|
157 | ks->gb_master_ali = GB_search(gb_main,buffer,GB_FIND); |
---|
158 | if (ks->gb_master_ali){ |
---|
159 | GB_remove_callback(ks->gb_master_ali,(GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE),gb_system_master_changed_cb,(int *)q); |
---|
160 | GB_add_callback (ks->gb_master_ali,(GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE),gb_system_master_changed_cb,(int *)q); |
---|
161 | } |
---|
162 | } |
---|
163 | GB_pop_my_security(gb_main); |
---|
164 | } |
---|
165 | } |
---|
166 | |
---|
167 | GB_ERROR gb_save_dictionary_data(GBDATA *gb_main,const char *key,const char *dict, int size) { |
---|
168 | /* if 'dict' is NULL, an existing directory gets deleted */ |
---|
169 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
---|
170 | GB_ERROR error = 0; |
---|
171 | gb_main = (GBDATA *)Main->data; |
---|
172 | if (key[0] == '@') { |
---|
173 | error = GB_export_error("No dictionaries for system fields"); |
---|
174 | } |
---|
175 | else { |
---|
176 | GBDATA *gb_key_data = Main->gb_key_data; |
---|
177 | GBDATA *gb_key,*gb_name,*gb_dict; |
---|
178 | GB_push_my_security(gb_main); |
---|
179 | gb_name = GB_find_string(gb_key_data,"@name",key,GB_MIND_CASE,down_2_level); |
---|
180 | if (gb_name){ |
---|
181 | gb_key= GB_get_father(gb_name); |
---|
182 | }else{ |
---|
183 | gb_key = gb_create_container(gb_key_data,"@key"); |
---|
184 | gb_name = gb_create(gb_key,"@name",GB_STRING); |
---|
185 | GB_write_string(gb_name,key); |
---|
186 | } |
---|
187 | if (dict) { |
---|
188 | gb_dict = gb_search(gb_key,"@dictionary",GB_BYTES,1); |
---|
189 | error = GB_write_bytes(gb_dict,dict,size); |
---|
190 | } |
---|
191 | else { |
---|
192 | gb_dict = GB_entry(gb_key, "@dictionary"); |
---|
193 | if (gb_dict) { |
---|
194 | GB_delete(gb_dict); /* delete existing dictionary */ |
---|
195 | } |
---|
196 | } |
---|
197 | GB_pop_my_security(gb_main); |
---|
198 | } |
---|
199 | if (!error){ |
---|
200 | GBQUARK q = gb_key_2_quark(Main,key); |
---|
201 | gb_load_single_key_data(gb_main,q); |
---|
202 | } |
---|
203 | return error; |
---|
204 | } |
---|
205 | |
---|
206 | GB_ERROR gb_load_key_data_and_dictionaries(GBDATA *gb_main){ |
---|
207 | GB_MAIN_TYPE *Main = GB_MAIN(gb_main); |
---|
208 | GBDATA *gb_key_data = gb_search(gb_main,GB_SYSTEM_FOLDER "/" GB_SYSTEM_KEY_DATA, GB_CREATE_CONTAINER,1); |
---|
209 | GBDATA *gb_key,*gb_next_key=0; |
---|
210 | int key; |
---|
211 | |
---|
212 | Main->gb_key_data = gb_key_data; |
---|
213 | if (!Main->local_mode) return 0; /* do not create anything at the client side */ |
---|
214 | |
---|
215 | GB_push_my_security(gb_main); |
---|
216 | |
---|
217 | /* First step: search unused keys and delete them */ |
---|
218 | for (gb_key = GB_entry(gb_key_data,"@key"); |
---|
219 | gb_key; |
---|
220 | gb_key = gb_next_key) |
---|
221 | { |
---|
222 | GBDATA *gb_name = GB_entry(gb_key,"@name"); |
---|
223 | const char *name = GB_read_char_pntr(gb_name); |
---|
224 | GBQUARK quark = gb_key_2_quark(Main,name); |
---|
225 | |
---|
226 | gb_next_key = GB_nextEntry(gb_key); |
---|
227 | |
---|
228 | if (quark<=0 || quark >= Main->sizeofkeys || !Main->keys[quark].key){ |
---|
229 | GB_delete(gb_key); /* delete unused key */ |
---|
230 | } |
---|
231 | } |
---|
232 | GB_create_index(gb_key_data, "@name", GB_MIND_CASE, Main->sizeofkeys*2); |
---|
233 | |
---|
234 | gb_key_2_quark(Main,"@name"); |
---|
235 | gb_key_2_quark(Main,"@key"); |
---|
236 | gb_key_2_quark(Main,"@dictionary"); |
---|
237 | gb_key_2_quark(Main,"compression_mask"); |
---|
238 | |
---|
239 | for (key=1;key<Main->sizeofkeys;key++){ |
---|
240 | char *k = Main->keys[key].key; |
---|
241 | if (!k) continue; |
---|
242 | gb_load_single_key_data(gb_main,key); |
---|
243 | } |
---|
244 | |
---|
245 | |
---|
246 | GB_pop_my_security(gb_main); |
---|
247 | return 0; |
---|
248 | } |
---|
249 | |
---|
250 | /* gain access to allow repair of broken compression |
---|
251 | * (see NT_fix_dict_compress) |
---|
252 | */ |
---|
253 | |
---|
254 | struct DictData { |
---|
255 | char *data; |
---|
256 | long size; |
---|
257 | }; |
---|
258 | |
---|
259 | struct DictData *GB_get_dictionary(GBDATA *gb_main, const char *key) { |
---|
260 | /* return DictData or |
---|
261 | * NULL if no dictionary or error occurred |
---|
262 | */ |
---|
263 | struct DictData *dd = (struct DictData*)GB_calloc(1, sizeof(*dd)); |
---|
264 | GB_ERROR error = gb_load_dictionary_data(gb_main, key, &dd->data, &dd->size); |
---|
265 | |
---|
266 | if (error || !dd->data) { |
---|
267 | GB_free_dictionary(dd); |
---|
268 | dd = NULL; |
---|
269 | if (error) GB_export_error(error); |
---|
270 | } |
---|
271 | |
---|
272 | return dd; |
---|
273 | } |
---|
274 | |
---|
275 | GB_ERROR GB_set_dictionary(GBDATA *gb_main, const char *key, const struct DictData *dd) { |
---|
276 | /* if 'dd' == NULL -> delete dictionary */ |
---|
277 | GB_ERROR error; |
---|
278 | if (dd) { |
---|
279 | error = gb_save_dictionary_data(gb_main, key, dd->data, dd->size); |
---|
280 | } |
---|
281 | else { |
---|
282 | error = gb_save_dictionary_data(gb_main, key, NULL, 0); |
---|
283 | } |
---|
284 | return error; |
---|
285 | } |
---|
286 | |
---|
287 | void GB_free_dictionary(struct DictData *dd) { |
---|
288 | if (dd) { |
---|
289 | if (dd->data) gbm_free_mem(dd->data, dd->size, GBM_DICT_INDEX); |
---|
290 | free(dd); |
---|
291 | } |
---|
292 | } |
---|