1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include "keyring-database.h"
28
29 #include <vdb/database.h>
30 #include <vdb/table.h>
31 #include <vdb/manager.h>
32 #include <vdb/schema.h>
33 #include <vdb/cursor.h>
34
35 #include "keyring-data.h"
36
37 static const char schema_text[] =
38 "version 1; "
39
40 " table projects : MyProjects #1 { "
41 " extern column U32 id = .id;"
42 " physical column U32 .id = id;"
43
44 " extern column ascii name = .name;"
45 " physical column ascii .name = name;"
46
47 " extern column ascii download_ticket = .download_ticket;"
48 " physical column ascii .download_ticket = download_ticket;"
49
50 " extern column ascii encryption_key = .encryption_key;"
51 " physical column ascii .encryption_key = encryption_key;"
52 " };"
53
54 " table objects : MyObjects #1 { "
55 " extern column U32 id = .id;"
56 " physical column U32 .id = id;"
57
58 " extern column ascii name = .name;"
59 " physical column ascii .name = name;"
60
61 " extern column ascii project = .project;"
62 " physical column ascii .project = project;"
63
64 " extern column ascii display_name = .display_name;"
65 " physical column ascii .display_name = display_name;"
66
67 " extern column U64 size = .size;"
68 " physical column U64 .size = size;"
69
70 " extern column ascii checksum = .checksum;"
71 " physical column ascii .checksum = checksum;"
72
73 " extern column ascii encryption_key = .encryption_key;"
74 " physical column ascii .encryption_key = encryption_key;"
75 " };"
76
77 " table keys : MyKeys #1 { "
78 " physical column U32 .id;"
79 " physical column ascii .value;"
80 " };"
81 "database keyring : KEYRING #1 { "
82 " table objects: MyObjects #1 object_inst;"
83 " table projects: MyProjects #1 project_inst;"
84 " table keys : MyKeys #1 keys_inst;"
85 "};";
86
87 static rc_t SaveProjects( const ProjectTable* data, VDatabase* db );
88 static rc_t SaveObjects ( const ObjectTable* data, VDatabase* db );
89 static rc_t LoadProjects( ProjectTable* data, const VDatabase* db );
90 static rc_t LoadObjects ( ObjectTable* data, const VDatabase* db );
91
KeyRingDatabaseSave(struct KeyRingData * self,struct KDirectory * wd,const char * path)92 rc_t KeyRingDatabaseSave ( struct KeyRingData* self, struct KDirectory* wd, const char* path )
93 {
94 rc_t rc;
95 VDBManager* vdbMgr;
96 rc = VDBManagerMakeUpdate( &vdbMgr, wd );
97 if (rc == 0)
98 {
99 VSchema* schema;
100 rc = VDBManagerMakeSchema(vdbMgr, &schema);
101 if (rc == 0)
102 {
103 rc = VSchemaParseText ( schema, "keyring_schema", schema_text, string_measure(schema_text, NULL) );
104 if (rc == 0)
105 { /* create a database */
106 VDatabase* db;
107 rc = VDBManagerCreateDB(vdbMgr, & db, schema, "keyring:KEYRING", kcmCreate | kcmMD5, path);
108 if (rc == 0)
109 {
110 rc_t rc2;
111 rc = SaveProjects(&self->projects, db);
112 if (rc == 0)
113 rc = SaveObjects(&self->objects, db);
114 /*TODO: SaveKeys */
115 rc2 = VDatabaseRelease(db);
116 if (rc == 0)
117 rc = rc2;
118 }
119
120 }
121 VSchemaRelease(schema);
122 }
123 VDBManagerRelease(vdbMgr);
124 }
125
126 return rc;
127 }
128
KeyRingDatabaseLoad(struct KeyRingData * self,const struct KDirectory * dir,const char * path)129 rc_t KeyRingDatabaseLoad ( struct KeyRingData* self, const struct KDirectory* dir, const char* path )
130 {
131 VDBManager* innerMgr;
132 rc_t rc = VDBManagerMakeUpdate( &innerMgr, (KDirectory*)dir );
133 if (rc == 0)
134 {
135 rc_t rc2;
136 const VDatabase* db;
137 rc = VDBManagerOpenDBRead(innerMgr, & db, NULL, "%s", path);
138 if (rc == 0)
139 {
140 rc = LoadProjects(&self->projects, db);
141 if (rc == 0)
142 rc = LoadObjects(&self->objects, db);
143 /*TODO: LoadKeys */
144 rc2 = VDatabaseRelease(db);
145 if (rc == 0)
146 rc = rc2;
147 }
148 rc2 = VDBManagerRelease(innerMgr);
149 if (rc == 0)
150 rc = rc2;
151 }
152
153 return rc;
154 }
155
156 static
SaveProjects(const ProjectTable * data,VDatabase * db)157 rc_t SaveProjects( const ProjectTable* data, VDatabase* db )
158 {
159 VTable* tbl;
160 rc_t rc = VDatabaseCreateTable(db, &tbl, "project_inst", kcmCreate | kcmMD5, "PROJECTS");
161 if (rc == 0)
162 {
163 rc_t rc2;
164 VCursor *cur;
165 rc = VTableCreateCursorWrite( tbl, &cur, kcmInsert );
166 if (rc == 0)
167 {
168 uint32_t id_idx, name_idx, dl_idx, enc_idx;
169 rc = VCursorAddColumn( cur, &id_idx, "id" );
170 rc = VCursorAddColumn( cur, &name_idx, "name" );
171 rc = VCursorAddColumn( cur, &dl_idx, "download_ticket" );
172 rc = VCursorAddColumn( cur, &enc_idx, "encryption_key" );
173 if (rc == 0)
174 {
175 rc = VCursorOpen( cur );
176 if (rc == 0)
177 {
178 const Project* p = (const Project*)BSTreeFirst(data);
179 while (rc == 0 && p != NULL)
180 {
181 rc = VCursorOpenRow( cur );
182
183 if (rc == 0) rc = VCursorWrite( cur, id_idx, sizeof(p->id) * 8, &p->id, 0, 1);
184 if (rc == 0) rc = VCursorWrite( cur, name_idx, StringLength(p->name) * 8, p->name->addr, 0, 1);
185 if (rc == 0) rc = VCursorWrite( cur, dl_idx, StringLength(p->download_ticket) * 8, p->download_ticket->addr, 0, 1);
186 if (rc == 0) rc = VCursorWrite( cur, enc_idx, StringLength(p->encryption_key) * 8, p->encryption_key->addr, 0, 1);
187
188 if (rc == 0) rc = VCursorCommitRow( cur );
189 if (rc == 0) rc = VCursorCloseRow( cur );
190
191 p = (const Project*)BSTNodeNext(&p->dad);
192 }
193 if (rc == 0)
194 rc = VCursorCommit( cur );
195 }
196 }
197 rc2 = VCursorRelease(cur);
198 if (rc == 0)
199 rc = rc2;
200 }
201
202 rc2 = VTableRelease(tbl);
203 if (rc == 0)
204 rc = rc2;
205 }
206 return rc;
207 }
208
209 static
SaveObjects(const ObjectTable * data,VDatabase * db)210 rc_t SaveObjects ( const ObjectTable* data, VDatabase* db )
211 {
212 VTable* tbl;
213 rc_t rc = VDatabaseCreateTable(db, &tbl, "object_inst", kcmCreate | kcmMD5, "OBJECTS");
214 if (rc == 0)
215 {
216 rc_t rc2;
217 VCursor *cur;
218 rc = VTableCreateCursorWrite( tbl, &cur, kcmInsert );
219 if (rc == 0)
220 {
221 uint32_t id_idx, name_idx, proj_idx, dname_idx, size_idx, csum_idx, enc_idx;
222 if (rc == 0) rc = VCursorAddColumn( cur, &id_idx, "id" );
223 if (rc == 0) rc = VCursorAddColumn( cur, &name_idx, "name" );
224 if (rc == 0) rc = VCursorAddColumn( cur, &proj_idx, "project" );
225 if (rc == 0) rc = VCursorAddColumn( cur, &dname_idx, "display_name" );
226 if (rc == 0) rc = VCursorAddColumn( cur, &size_idx, "size" );
227 if (rc == 0) rc = VCursorAddColumn( cur, &csum_idx, "checksum" );
228 if (rc == 0) rc = VCursorAddColumn( cur, &enc_idx, "encryption_key" );
229
230 if (rc == 0)
231 {
232 rc = VCursorOpen( cur );
233 if (rc == 0)
234 {
235 const Object* obj = (const Object*)BSTreeFirst(data);
236 while (rc == 0 && obj != NULL)
237 {
238 rc = VCursorOpenRow( cur );
239
240 if (rc == 0) rc = VCursorWrite( cur, id_idx, sizeof(obj->id) * 8, &obj->id, 0, 1);
241 if (rc == 0) rc = VCursorWrite( cur, name_idx, StringLength(obj->name) * 8, obj->name->addr, 0, 1);
242 if (rc == 0) rc = VCursorWrite( cur, proj_idx, StringLength(obj->project) * 8, obj->project->addr, 0, 1);
243 if (rc == 0) rc = VCursorWrite( cur, dname_idx, StringLength(obj->display_name) * 8, obj->display_name->addr, 0, 1);
244 if (rc == 0) rc = VCursorWrite( cur, size_idx, sizeof(obj->size) * 8, &obj->size, 0, 1);
245 if (rc == 0) rc = VCursorWrite( cur, csum_idx, StringLength(obj->encryption_key) * 8, obj->encryption_key->addr, 0, 1);
246 if (rc == 0) rc = VCursorWrite( cur, enc_idx, StringLength(obj->encryption_key) * 8, obj->encryption_key->addr, 0, 1);
247
248 if (rc == 0) rc = VCursorCommitRow( cur );
249 if (rc == 0) rc = VCursorCloseRow( cur );
250
251 obj = (const Object*)BSTNodeNext(&obj->dad);
252 }
253 if (rc == 0) rc = VCursorCommit( cur );
254 }
255 }
256 rc2 = VCursorRelease(cur);
257 if (rc == 0)
258 rc = rc2;
259 }
260
261 rc2 = VTableRelease(tbl);
262 if (rc == 0)
263 rc = rc2;
264 }
265 return rc;
266 }
267
268 static size_t CursorCacheSize = 32*1024;
269
270 static
HasData(const VTable * tbl)271 bool HasData(const VTable* tbl)
272 {
273 bool ret = false;
274 KNamelist *names;
275 if (VTableListCol(tbl, &names) == 0)
276 {
277 uint32_t n;
278 ret = KNamelistCount( names, &n ) == 0 && n > 0;
279 }
280 KNamelistRelease( names );
281 return ret;
282 }
283
284 static
LoadProjects(ProjectTable * data,const VDatabase * db)285 rc_t LoadProjects( ProjectTable* data, const VDatabase* db )
286 {
287 const VTable* tbl;
288 rc_t rc = VDatabaseOpenTableRead(db, &tbl, "PROJECTS");
289 if (rc == 0)
290 {
291 rc_t rc2;
292 const VCursor *cur;
293
294 rc = VTableCreateCachedCursorRead( tbl, &cur, CursorCacheSize );
295 if (rc == 0)
296 {
297 uint32_t id_idx, name_idx, dl_idx, enc_idx;
298 rc = VCursorAddColumn( cur, &id_idx, "id" );
299 if (rc == 0) rc = VCursorAddColumn( cur, &name_idx, "name" );
300 if (rc == 0) rc = VCursorAddColumn( cur, &dl_idx, "download_ticket" );
301 if (rc == 0) rc = VCursorAddColumn( cur, &enc_idx, "encryption_key" );
302 if (rc == 0 && HasData(tbl))
303 {
304 rc = VCursorOpen( cur );
305 if (rc == 0)
306 {
307 int64_t first;
308 uint64_t count;
309 rc = VCursorIdRange( cur, 0, &first, &count );
310 if (rc == 0)
311 {
312 uint64_t i;
313 for (i=0; i < count; ++i)
314 {
315 const void* ptr;
316 uint32_t elem_count;
317 uint32_t id;
318 String name;
319 String download_ticket;
320 String encryption_key;
321
322 rc = VCursorSetRowId(cur, first + i);
323 if (rc == 0) rc = VCursorOpenRow( cur );
324
325 if (rc == 0) rc = VCursorCellData( cur, id_idx, NULL, &ptr, NULL, NULL);
326 if (rc == 0) id = *(uint32_t*)ptr;
327 if (rc == 0) rc = VCursorCellData( cur, name_idx, NULL, &ptr, NULL, &elem_count);
328 if (rc == 0) StringInit(&name, (const char*)ptr, elem_count, elem_count);
329 if (rc == 0) rc = VCursorCellData( cur, dl_idx, NULL, &ptr, NULL, &elem_count);
330 if (rc == 0) StringInit(&download_ticket, (const char*)ptr, elem_count, elem_count);
331 if (rc == 0) rc = VCursorCellData( cur, enc_idx, NULL, &ptr, NULL, &elem_count);
332 if (rc == 0) StringInit(&encryption_key, (const char*)ptr, elem_count, elem_count);
333
334 if (rc == 0) rc = KeyRingDataInsertProject(data, id, &name, &download_ticket, &encryption_key);
335 if (rc == 0) rc = VCursorCloseRow( cur );
336 if (rc != 0)
337 break;
338 }
339 }
340 }
341 }
342 rc2 = VCursorRelease(cur);
343 if (rc == 0)
344 rc = rc2;
345 }
346
347 rc2 = VTableRelease(tbl);
348 if (rc == 0)
349 rc = rc2;
350 }
351 return rc;
352 }
353
354 static
LoadObjects(ObjectTable * data,const VDatabase * db)355 rc_t LoadObjects ( ObjectTable* data, const VDatabase* db )
356 {
357 const VTable* tbl;
358 rc_t rc = VDatabaseOpenTableRead(db, &tbl, "OBJECTS");
359 if (rc == 0)
360 {
361 rc_t rc2;
362 const VCursor *cur;
363
364 rc = VTableCreateCachedCursorRead( tbl, &cur, CursorCacheSize );
365 if (rc == 0)
366 {
367 uint32_t id_idx, name_idx, proj_idx, dname_idx, size_idx, csum_idx, enc_idx;
368 if (rc == 0) rc = VCursorAddColumn( cur, &id_idx, "id" );
369 if (rc == 0) rc = VCursorAddColumn( cur, &name_idx, "name" );
370 if (rc == 0) rc = VCursorAddColumn( cur, &proj_idx, "project" );
371 if (rc == 0) rc = VCursorAddColumn( cur, &dname_idx, "display_name" );
372 if (rc == 0) rc = VCursorAddColumn( cur, &size_idx, "size" );
373 if (rc == 0) rc = VCursorAddColumn( cur, &csum_idx, "checksum" );
374 if (rc == 0) rc = VCursorAddColumn( cur, &enc_idx, "encryption_key" );
375 if (rc == 0 && HasData(tbl))
376 {
377 rc = VCursorOpen( cur );
378 if (rc == 0)
379 {
380 int64_t first;
381 uint64_t count;
382 rc = VCursorIdRange( cur, 0, &first, &count );
383 if (rc == 0)
384 {
385 uint64_t i;
386 for (i=0; i < count; ++i)
387 {
388 const void* ptr;
389 uint32_t elem_count;
390 uint32_t id;
391 String name;
392 String project;
393 String display_name;
394 uint64_t size;
395 String checksum;
396 String encryption_key;
397
398 rc = VCursorSetRowId(cur, first + i);
399 if (rc == 0) rc = VCursorOpenRow( cur );
400
401 if (rc == 0) rc = VCursorCellData( cur, id_idx, NULL, &ptr, NULL, NULL);
402 if (rc == 0) id = *(uint32_t*)ptr;
403
404 if (rc == 0) rc = VCursorCellData( cur, name_idx, NULL, &ptr, NULL, &elem_count);
405 if (rc == 0) StringInit(&name, (const char*)ptr, elem_count, elem_count);
406
407 if (rc == 0) rc = VCursorCellData( cur, proj_idx, NULL, &ptr, NULL, &elem_count);
408 if (rc == 0) StringInit(&project, (const char*)ptr, elem_count, elem_count);
409
410 if (rc == 0) rc = VCursorCellData( cur, dname_idx, NULL, &ptr, NULL, &elem_count);
411 if (rc == 0) StringInit(&display_name, (const char*)ptr, elem_count, elem_count);
412
413 if (rc == 0) rc = VCursorCellData( cur, size_idx, NULL, &ptr, NULL, NULL);
414 if (rc == 0) size = *(uint32_t*)ptr;
415
416 if (rc == 0) rc = VCursorCellData( cur, enc_idx, NULL, &ptr, NULL, &elem_count);
417 if (rc == 0) StringInit(&encryption_key, (const char*)ptr, elem_count, elem_count);
418
419 if (rc == 0) rc = VCursorCellData( cur, csum_idx, NULL, &ptr, NULL, &elem_count);
420 if (rc == 0) StringInit(&checksum, (const char*)ptr, elem_count, elem_count);
421
422 if (rc == 0) rc = KeyRingDataInsertObject(data, id, &name, &project, &display_name, size, &checksum, &encryption_key);
423 if (rc == 0) rc = VCursorCloseRow( cur );
424 if (rc != 0)
425 break;
426 }
427 }
428 }
429 }
430 rc2 = VCursorRelease(cur);
431 if (rc == 0)
432 rc = rc2;
433 }
434
435 rc2 = VTableRelease(tbl);
436 if (rc == 0)
437 rc = rc2;
438 }
439 return rc;
440 }
441
442