00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00292
00293 #include "midas.h"
00294 #include "msystem.h"
00295 #include <assert.h>
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 DATABASE *_database;
00308 INT _database_entries = 0;
00309
00310 static RECORD_LIST *_record_list;
00311 static INT _record_list_entries = 0;
00312
00313 extern char *tid_name[];
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 void *malloc_key(DATABASE_HEADER * pheader, INT size)
00325 {
00326 FREE_DESCRIP *pfree, *pfound, *pprev = NULL;
00327
00328 if (size == 0)
00329 return NULL;
00330
00331
00332 size = ALIGN8(size);
00333
00334
00335 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
00336
00337 while (pfree->size < size && pfree->next_free) {
00338 pprev = pfree;
00339 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00340 }
00341
00342
00343 if (pfree->size < size)
00344 return 0;
00345
00346 pfound = pfree;
00347
00348
00349 if (pfree == (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key)) {
00350 if (size < pfree->size) {
00351
00352 pheader->first_free_key += size;
00353 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
00354
00355 pfree->size = pfound->size - size;
00356 pfree->next_free = pfound->next_free;
00357 } else {
00358
00359 pheader->first_free_key = pfree->next_free;
00360 }
00361 } else {
00362
00363 if (pfound->size - size < sizeof(FREE_DESCRIP)) {
00364
00365 pprev->next_free = pfound->next_free;
00366 } else {
00367
00368 pfree = (FREE_DESCRIP *) ((char *) pfound + size);
00369
00370 pfree->size = pfound->size - size;
00371 pfree->next_free = pfound->next_free;
00372
00373 pprev->next_free = (PTYPE) pfree - (PTYPE) pheader;
00374 }
00375 }
00376
00377
00378 memset(pfound, 0, size);
00379
00380 return pfound;
00381 }
00382
00383
00384 void free_key(DATABASE_HEADER * pheader, void *address, INT size)
00385 {
00386 FREE_DESCRIP *pfree, *pprev, *pnext;
00387
00388 if (size == 0)
00389 return;
00390
00391
00392 size = ALIGN8(size);
00393
00394 pfree = (FREE_DESCRIP *) address;
00395 pprev = NULL;
00396
00397
00398 memset(address, 0, size);
00399
00400
00401 if ((PTYPE) address - (PTYPE) pheader < pheader->first_free_key) {
00402 pfree->size = size;
00403 pfree->next_free = pheader->first_free_key;
00404 pheader->first_free_key = (PTYPE) address - (PTYPE) pheader;
00405 } else {
00406
00407 pprev = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
00408
00409 while (pprev->next_free < (PTYPE) address - (PTYPE) pheader) {
00410 if (pprev->next_free <= 0) {
00411 cm_msg(MERROR, "free_key",
00412 "database is corrupted: pprev=0x%x, pprev->next_free=%d",
00413 pprev, pprev->next_free);
00414 return;
00415 }
00416 pprev = (FREE_DESCRIP *) ((char *) pheader + pprev->next_free);
00417 }
00418
00419 pfree->size = size;
00420 pfree->next_free = pprev->next_free;
00421
00422 pprev->next_free = (PTYPE) pfree - (PTYPE) pheader;
00423 }
00424
00425
00426 pnext = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00427 if ((PTYPE) pnext == (PTYPE) pfree + pfree->size) {
00428 pfree->size += pnext->size;
00429 pfree->next_free = pnext->next_free;
00430
00431 memset(pnext, 0, pnext->size);
00432 }
00433
00434
00435 if (pprev && pprev->next_free == (PTYPE) pprev - (PTYPE) pheader + pprev->size) {
00436 pprev->size += pfree->size;
00437 pprev->next_free = pfree->next_free;
00438
00439 memset(pfree, 0, pfree->size);
00440 }
00441 }
00442
00443
00444 void *malloc_data(DATABASE_HEADER * pheader, INT size)
00445 {
00446 FREE_DESCRIP *pfree, *pfound, *pprev = NULL;
00447
00448 if (size == 0)
00449 return NULL;
00450
00451
00452 size = ALIGN8(size);
00453
00454
00455 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
00456
00457 while (pfree->size < size && pfree->next_free) {
00458 pprev = pfree;
00459 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00460 }
00461
00462
00463 if (pfree->size < size)
00464 return 0;
00465
00466 pfound = pfree;
00467
00468
00469 if (pfree == (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data)) {
00470 if (size < pfree->size) {
00471
00472 pheader->first_free_data += size;
00473 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
00474
00475 pfree->size = pfound->size - size;
00476 pfree->next_free = pfound->next_free;
00477 } else {
00478
00479 pheader->first_free_data = pfree->next_free;
00480 }
00481 } else {
00482
00483 if (pfound->size - size < sizeof(FREE_DESCRIP)) {
00484
00485 pprev->next_free = pfound->next_free;
00486 } else {
00487
00488 pfree = (FREE_DESCRIP *) ((char *) pfound + size);
00489
00490 pfree->size = pfound->size - size;
00491 pfree->next_free = pfound->next_free;
00492
00493 pprev->next_free = (PTYPE) pfree - (PTYPE) pheader;
00494 }
00495 }
00496
00497
00498 memset(pfound, 0, size);
00499
00500 return pfound;
00501 }
00502
00503
00504 void free_data(DATABASE_HEADER * pheader, void *address, INT size)
00505 {
00506 FREE_DESCRIP *pfree, *pprev, *pnext;
00507
00508 if (size == 0)
00509 return;
00510
00511
00512 size = ALIGN8(size);
00513
00514 pfree = (FREE_DESCRIP *) address;
00515 pprev = NULL;
00516
00517
00518 memset(address, 0, size);
00519
00520
00521 if ((PTYPE) address - (PTYPE) pheader < pheader->first_free_data) {
00522 pfree->size = size;
00523 pfree->next_free = pheader->first_free_data;
00524 pheader->first_free_data = (PTYPE) address - (PTYPE) pheader;
00525 } else {
00526
00527 pprev = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
00528
00529 while (pprev->next_free < (PTYPE) address - (PTYPE) pheader) {
00530 if (pprev->next_free <= 0) {
00531 cm_msg(MERROR, "free_data",
00532 "database is corrupted: pprev=0x%x, pprev->next_free=%d",
00533 pprev, pprev->next_free);
00534 return;
00535 }
00536
00537 pprev = (FREE_DESCRIP *) ((char *) pheader + pprev->next_free);
00538 }
00539
00540 pfree->size = size;
00541 pfree->next_free = pprev->next_free;
00542
00543 pprev->next_free = (PTYPE) pfree - (PTYPE) pheader;
00544 }
00545
00546
00547 pnext = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00548 if ((PTYPE) pnext == (PTYPE) pfree + pfree->size) {
00549 pfree->size += pnext->size;
00550 pfree->next_free = pnext->next_free;
00551
00552 memset(pnext, 0, pnext->size);
00553 }
00554
00555
00556 if (pprev && pprev->next_free == (PTYPE) pprev - (PTYPE) pheader + pprev->size) {
00557 pprev->size += pfree->size;
00558 pprev->next_free = pfree->next_free;
00559
00560 memset(pfree, 0, pfree->size);
00561 }
00562 }
00563
00564
00565 void *realloc_data(DATABASE_HEADER * pheader, void *address, INT old_size, INT new_size)
00566 {
00567 void *tmp = NULL, *pnew;
00568
00569 if (old_size) {
00570 tmp = malloc(old_size);
00571 if (tmp == NULL)
00572 return NULL;
00573
00574 memcpy(tmp, address, old_size);
00575 free_data(pheader, address, old_size);
00576 }
00577
00578 pnew = malloc_data(pheader, new_size);
00579
00580 if (pnew && old_size)
00581 memcpy(pnew, tmp, old_size < new_size ? old_size : new_size);
00582
00583 if (old_size)
00584 free(tmp);
00585
00586 return pnew;
00587 }
00588
00589
00590 char *strcomb(char **list)
00591
00592 {
00593 INT i, j;
00594 static char *str = NULL;
00595
00596
00597 for (i = 0, j = 0; list[i]; i++)
00598 j += strlen(list[i]) + 1;
00599 j += 1;
00600
00601 if (str == NULL)
00602 str = (char *) malloc(j);
00603 else
00604 str = (char *) realloc(str, j);
00605
00606 str[0] = 0;
00607 for (i = 0; list[i]; i++) {
00608 strcat(str, list[i]);
00609 strcat(str, "\n");
00610 }
00611
00612 return str;
00613 }
00614
00615
00616 INT print_key_info(HNDLE hDB, HNDLE hKey, KEY * pkey, INT level, void *info)
00617 {
00618 int i;
00619 char *p;
00620
00621 p = (char *) info;
00622
00623 sprintf(p + strlen(p), "%08X %08X %04X ",
00624 (int)(hKey - sizeof(DATABASE_HEADER)),
00625 (int)(pkey->data - sizeof(DATABASE_HEADER)), (int)pkey->total_size);
00626
00627 for (i = 0; i < level; i++)
00628 sprintf(p + strlen(p), " ");
00629
00630 sprintf(p + strlen(p), "%s\n", pkey->name);
00631
00632 return SUCCESS;
00633 }
00634
00635 INT db_show_mem(HNDLE hDB, char *result, INT buf_size, BOOL verbose)
00636 {
00637 DATABASE_HEADER *pheader;
00638 INT total_size_key, total_size_data;
00639 FREE_DESCRIP *pfree;
00640
00641 db_lock_database(hDB);
00642
00643 pheader = _database[hDB - 1].database_header;
00644
00645 sprintf(result,
00646 "Database header size is 0x%04X, all following values are offset by this!\nKey area 0x00000000 - 0x%08X\nData area 0x%08X - 0x%08X\n\n",
00647 (int)sizeof(DATABASE_HEADER), pheader->key_size - 1,
00648 pheader->key_size, pheader->key_size + pheader->data_size);
00649
00650 strcat(result, "Keylist:\n");
00651 strcat(result, "--------\n");
00652 total_size_key = 0;
00653 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
00654
00655 while ((PTYPE) pfree != (PTYPE) pheader) {
00656 total_size_key += pfree->size;
00657 sprintf(result + strlen(result),
00658 "Free block at 0x%08X, size 0x%08X, next 0x%08X\n",
00659 (int)((PTYPE) pfree - (PTYPE) pheader - sizeof(DATABASE_HEADER)),
00660 pfree->size,
00661 pfree->next_free ? (int)(pfree->next_free - sizeof(DATABASE_HEADER)) : 0);
00662 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00663 }
00664
00665 strcat(result, "\nData:\n");
00666 strcat(result, "-----\n");
00667 total_size_data = 0;
00668 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
00669
00670 while ((PTYPE) pfree != (PTYPE) pheader) {
00671 total_size_data += pfree->size;
00672 sprintf(result + strlen(result),
00673 "Free block at 0x%08X, size 0x%08X, next 0x%08X\n",
00674 (int)((PTYPE) pfree - (PTYPE) pheader - sizeof(DATABASE_HEADER)),
00675 pfree->size,
00676 pfree->next_free ? (int)(pfree->next_free - sizeof(DATABASE_HEADER)) : 0);
00677 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00678 }
00679 sprintf(result + strlen(result),
00680 "\nTotal size: %1d (0x%08X) keylist, %1d (0x%08X) data\n",
00681 total_size_key, total_size_key, total_size_data, total_size_data);
00682 sprintf(result + strlen(result),
00683 "\nFree: %1d (%1.1lf%%) keylist, %1d (%1.1lf%%) data\n",
00684 total_size_key,
00685 100 * (double) total_size_key / pheader->key_size,
00686 total_size_data, 100 * (double) total_size_data / pheader->data_size);
00687
00688 if (verbose) {
00689 sprintf(result + strlen(result), "\n\n");
00690 sprintf(result + strlen(result), "Key Data Size\n");
00691 sprintf(result + strlen(result), "------------------------\n");
00692 db_scan_tree(hDB, pheader->root_key, 0, print_key_info, result);
00693 }
00694
00695 db_unlock_database(hDB);
00696
00697 return DB_SUCCESS;
00698 }
00699
00700
00701 static int db_validate_key_offset(DATABASE_HEADER * pheader, int offset)
00702
00703 {
00704 if (offset != 0 && offset < (int) sizeof(DATABASE_HEADER))
00705 return 0;
00706
00707 if (offset > (int) sizeof(DATABASE_HEADER) + pheader->key_size)
00708 return 0;
00709
00710 return 1;
00711 }
00712
00713 static int db_validate_data_offset(DATABASE_HEADER * pheader, int offset)
00714
00715 {
00716 if (offset != 0 && offset < (int) sizeof(DATABASE_HEADER))
00717 return 0;
00718
00719 if (offset > (int) sizeof(DATABASE_HEADER) + pheader->key_size + pheader->data_size)
00720 return 0;
00721
00722 return 1;
00723 }
00724
00725 static int db_validate_hkey(DATABASE_HEADER * pheader, HNDLE hKey)
00726 {
00727 return db_validate_key_offset(pheader, hKey);
00728 }
00729
00730 static int db_validate_key(DATABASE_HEADER * pheader, int recurse,
00731 const char *path, KEY * pkey)
00732 {
00733 KEYLIST *pkeylist;
00734 int i;
00735 static time_t t_min = 0, t_max;
00736
00737 if (!db_validate_key_offset(pheader, (PTYPE) pkey - (PTYPE) pheader)) {
00738 cm_msg(MERROR, "db_validate_key",
00739 "Warning: database corruption, key \"%s\", data 0x%08X", path,
00740 pkey->data - sizeof(DATABASE_HEADER));
00741 return 0;
00742 }
00743
00744 if (!db_validate_data_offset(pheader, pkey->data)) {
00745 cm_msg(MERROR, "db_validate_key",
00746 "Warning: database corruption, data \"%s\", data 0x%08X",
00747 path, pkey->data - sizeof(DATABASE_HEADER));
00748 return 0;
00749 }
00750
00751
00752 if (pkey->type >= TID_LAST) {
00753 cm_msg(MERROR, "db_validate_key",
00754 "Warning: invalid key type, key \"%s\", type %d", path, pkey->type);
00755 return 0;
00756 }
00757
00758
00759 if ((pkey->total_size < 0) || (pkey->total_size > pheader->key_size)) {
00760 cm_msg(MERROR, "db_validate_key",
00761 "Warning: invalid key \"%s\" total_size: %d", path, pkey->total_size);
00762 return 0;
00763 }
00764
00765 if ((pkey->item_size < 0) || (pkey->item_size > pheader->key_size)) {
00766 cm_msg(MERROR, "db_validate_key",
00767 "Warning: invalid key \"%s\" item_size: %d", path, pkey->item_size);
00768 return 0;
00769 }
00770
00771 if ((pkey->num_values < 0) || (pkey->num_values > pheader->key_size)) {
00772 cm_msg(MERROR, "db_validate_key",
00773 "Warning: invalid key \"%s\" num_values: %d", path, pkey->num_values);
00774 return 0;
00775 }
00776
00777
00778 if (pkey->total_size != pkey->item_size * pkey->num_values) {
00779 cm_msg(MINFO, "db_validate_key",
00780 "Warning: corrected key \"%s\" size: total_size=%d, should be %d*%d=%d",
00781 path, pkey->total_size, pkey->item_size, pkey->num_values,
00782 pkey->item_size * pkey->num_values);
00783 pkey->total_size = pkey->item_size * pkey->num_values;
00784 }
00785
00786
00787 if ((pkey->
00788 access_mode & ~(MODE_READ | MODE_WRITE | MODE_DELETE |
00789 MODE_EXCLUSIVE | MODE_ALLOC))) {
00790 cm_msg(MERROR, "db_validate_key",
00791 "Warning: invalid access mode, key \"%s\", mode %d", path,
00792 pkey->access_mode);
00793 return 0;
00794 }
00795
00796
00797 if (t_min == 0) {
00798 t_min = ss_time() - 3600 * 24 * 365 * 10;
00799 t_max = ss_time() + 3600 * 24 * 365 * 10;
00800 }
00801
00802 if (pkey->last_written > 0 &&
00803 (pkey->last_written < t_min || pkey->last_written > t_max)) {
00804 cm_msg(MERROR, "db_validate_key",
00805 "Warning: invalid access time, key \"%s\", time %d", path,
00806 pkey->last_written);
00807 return 0;
00808 }
00809
00810 if (pkey->type == TID_KEY && recurse) {
00811
00812
00813 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
00814
00815 if (pkeylist->num_keys != 0 &&
00816 (pkeylist->first_key == 0
00817 || !db_validate_key_offset(pheader, pkeylist->first_key))) {
00818 cm_msg(MERROR, "db_validate_key",
00819 "Warning: database corruption, key \"%s\", first_key 0x%08X",
00820 path, pkeylist->first_key - sizeof(DATABASE_HEADER));
00821 return 0;
00822 }
00823
00824
00825 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
00826
00827 for (i = 0; i < pkeylist->num_keys; i++) {
00828 char buf[1024];
00829 sprintf(buf, "%s/%s", path, pkey->name);
00830
00831 if (!db_validate_key_offset(pheader, pkey->next_key)) {
00832 cm_msg(MERROR, "db_validate_key",
00833 "Warning: database corruption, key \"%s\", next_key 0x%08X",
00834 buf, pkey->next_key - sizeof(DATABASE_HEADER));
00835 return 0;
00836 }
00837
00838 if (pkey->type == TID_KEY)
00839 if (!db_validate_key(pheader, recurse + 1, buf, pkey))
00840 return 0;
00841
00842 pkey = (KEY *) ((char *) pheader + pkey->next_key);
00843 }
00844 }
00845
00846 return 1;
00847 }
00848
00849
00850 static int db_validate_db(DATABASE_HEADER * pheader)
00851 {
00852 int total_size_key = 0;
00853 int total_size_data = 0;
00854 double ratio;
00855 FREE_DESCRIP *pfree;
00856
00857
00858
00859 if (!db_validate_key_offset(pheader, pheader->first_free_key)) {
00860 cm_msg(MERROR, "db_validate_db",
00861 "Warning: database corruption, first_free_key 0x%08X",
00862 pheader->first_free_key - sizeof(DATABASE_HEADER));
00863 return 0;
00864 }
00865
00866 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
00867
00868 while ((PTYPE) pfree != (PTYPE) pheader) {
00869 if (pfree->next_free != 0 && !db_validate_key_offset(pheader, pfree->next_free)) {
00870 cm_msg(MERROR, "db_validate_db",
00871 "Warning: database corruption, next_free 0x%08X",
00872 pfree->next_free - sizeof(DATABASE_HEADER));
00873 return 0;
00874 }
00875
00876 total_size_key += pfree->size;
00877 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00878 }
00879
00880 ratio = ((double) (pheader->key_size - total_size_key)) / ((double) pheader->key_size);
00881 if (ratio > 0.9)
00882 cm_msg(MERROR, "db_validate_db",
00883 "Warning: database key area is %.0f%% full", ratio * 100.0);
00884
00885 if (total_size_key > pheader->key_size) {
00886 cm_msg(MERROR, "db_validate_db",
00887 "Warning: database corruption, total_key_size 0x%08X", total_size_key);
00888 return 0;
00889 }
00890
00891
00892
00893 if (!db_validate_data_offset(pheader, pheader->first_free_data)) {
00894 cm_msg(MERROR, "db_validate_db",
00895 "Warning: database corruption, first_free_data 0x%08X",
00896 pheader->first_free_data - sizeof(DATABASE_HEADER));
00897 return 0;
00898 }
00899
00900 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
00901
00902 while ((PTYPE) pfree != (PTYPE) pheader) {
00903 if (pfree->next_free != 0 && !db_validate_data_offset(pheader, pfree->next_free)) {
00904 cm_msg(MERROR, "db_validate_db",
00905 "Warning: database corruption, next_free 0x%08X",
00906 pfree->next_free - sizeof(DATABASE_HEADER));
00907 return 0;
00908 }
00909
00910 total_size_data += pfree->size;
00911 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
00912 }
00913
00914 ratio =
00915 ((double) (pheader->data_size - total_size_data)) / ((double) pheader->data_size);
00916 if (ratio > 0.9)
00917 cm_msg(MERROR, "db_validate_db",
00918 "Warning: database data area is %.0f%% full", ratio * 100.0);
00919
00920 if (total_size_data > pheader->data_size) {
00921 cm_msg(MERROR, "db_validate_db",
00922 "Warning: database corruption, total_size_data 0x%08X", total_size_key);
00923 return 0;
00924 }
00925
00926
00927
00928 if (!db_validate_key_offset(pheader, pheader->root_key)) {
00929 cm_msg(MERROR, "db_validate_db",
00930 "Warning: database corruption, root_key 0x%08X",
00931 pheader->root_key - sizeof(DATABASE_HEADER));
00932 return 0;
00933 }
00934
00935 return db_validate_key(pheader, 1, "", (KEY *) ((char *) pheader + pheader->root_key));
00936 }
00937
00938
00939 #endif
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 INT db_open_database(char *database_name, INT database_size,
00953 HNDLE * hDB, char *client_name)
00954 {
00955 if (rpc_is_remote())
00956 return rpc_call(RPC_DB_OPEN_DATABASE, database_name, database_size,
00957 hDB, client_name);
00958
00959 #ifdef LOCAL_ROUTINES
00960 {
00961 INT i, status;
00962 HNDLE handle;
00963 DATABASE_CLIENT *pclient;
00964 BOOL shm_created;
00965 HNDLE shm_handle;
00966 DATABASE_HEADER *pheader;
00967 KEY *pkey;
00968 KEYLIST *pkeylist;
00969 FREE_DESCRIP *pfree;
00970 BOOL call_watchdog;
00971 DWORD timeout;
00972
00973 if (database_size < 0 || database_size > 10E7) {
00974 cm_msg(MERROR, "db_open_database", "invalid database size");
00975 return DB_INVALID_PARAM;
00976 }
00977
00978
00979 if (strlen(database_name) >= NAME_LENGTH)
00980 database_name[NAME_LENGTH] = 0;
00981
00982
00983 if (_database_entries == 0) {
00984 _database = (DATABASE *) malloc(sizeof(DATABASE));
00985 memset(_database, 0, sizeof(DATABASE));
00986 if (_database == NULL) {
00987 *hDB = 0;
00988 return DB_NO_MEMORY;
00989 }
00990
00991 _database_entries = 1;
00992 i = 0;
00993 } else {
00994
00995 for (i = 0; i < _database_entries; i++)
00996 if (_database[i].attached && equal_ustring(_database[i].name, database_name)) {
00997
00998 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_MTHREAD) {
00999 if (_database[i].index == ss_gettid()) {
01000 *hDB = i + 1;
01001 return DB_SUCCESS;
01002 }
01003 } else {
01004 *hDB = i + 1;
01005 return DB_SUCCESS;
01006 }
01007 }
01008
01009
01010 for (i = 0; i < _database_entries; i++)
01011 if (!_database[i].attached)
01012 break;
01013
01014
01015 if (i == _database_entries) {
01016 _database =
01017 (DATABASE *) realloc(_database,
01018 sizeof(DATABASE) * (_database_entries + 1));
01019 memset(&_database[_database_entries], 0, sizeof(DATABASE));
01020
01021 _database_entries++;
01022 if (_database == NULL) {
01023 _database_entries--;
01024 *hDB = 0;
01025 return DB_NO_MEMORY;
01026 }
01027 }
01028 }
01029
01030 handle = (HNDLE) i;
01031
01032
01033 status = ss_shm_open(database_name,
01034 sizeof(DATABASE_HEADER) +
01035 2 * ALIGN8(database_size / 2),
01036 (void **) &(_database[(INT) handle].
01037 database_header), &shm_handle);
01038
01039 if (status == SS_NO_MEMORY || status == SS_FILE_ERROR) {
01040 *hDB = 0;
01041 return DB_INVALID_NAME;
01042 }
01043
01044
01045 pheader = _database[handle].database_header;
01046
01047
01048 strcpy(_database[handle].name, database_name);
01049
01050 shm_created = (status == SS_CREATED);
01051
01052
01053
01054
01055 if (shm_created && pheader->name[0] == 0) {
01056
01057 memset(pheader, 0, sizeof(DATABASE_HEADER) + 2 * ALIGN8(database_size / 2));
01058
01059 strcpy(pheader->name, database_name);
01060 pheader->key_size = ALIGN8(database_size / 2);
01061 pheader->data_size = ALIGN8(database_size / 2);
01062 pheader->root_key = sizeof(DATABASE_HEADER);
01063 pheader->first_free_key = sizeof(DATABASE_HEADER);
01064 pheader->first_free_data = sizeof(DATABASE_HEADER) + pheader->key_size;
01065
01066
01067 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
01068 pfree->size = pheader->key_size;
01069 pfree->next_free = 0;
01070
01071 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
01072 pfree->size = pheader->data_size;
01073 pfree->next_free = 0;
01074
01075
01076 pkey = (KEY *) malloc_key(pheader, sizeof(KEY));
01077
01078
01079 pkey->type = TID_KEY;
01080 pkey->num_values = 1;
01081 pkey->access_mode = MODE_READ | MODE_WRITE | MODE_DELETE;
01082 strcpy(pkey->name, "root");
01083 pkey->parent_keylist = 0;
01084
01085
01086 pkeylist = (KEYLIST *) malloc_key(pheader, sizeof(KEYLIST));
01087
01088
01089 pkey->data = (PTYPE) pkeylist - (PTYPE) pheader;
01090 pkey->item_size = sizeof(KEYLIST);
01091 pkey->total_size = sizeof(KEYLIST);
01092
01093 pkeylist->parent = (PTYPE) pkey - (PTYPE) pheader;
01094 pkeylist->num_keys = 0;
01095 pkeylist->first_key = 0;
01096 }
01097
01098
01099 status = ss_mutex_create(database_name, &(_database[handle].mutex));
01100 if (status != SS_SUCCESS && status != SS_CREATED) {
01101 *hDB = 0;
01102 return DB_NO_MUTEX;
01103 }
01104 _database[handle].lock_cnt = 0;
01105
01106
01107 db_lock_database(handle + 1);
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 pheader->num_clients = 0;
01119 pheader->max_client_index = 0;
01120 for (i = 0; i < MAX_CLIENTS; i++) {
01121 if (pheader->client[i].pid == 0)
01122 continue;
01123 pheader->num_clients++;
01124 pheader->max_client_index = i + 1;
01125 }
01126
01127
01128
01129
01130
01131
01132 for (i = 0; i < MAX_CLIENTS; i++)
01133 if (pheader->client[i].pid == 0)
01134 break;
01135
01136 if (i == MAX_CLIENTS) {
01137 db_unlock_database(handle + 1);
01138 *hDB = 0;
01139 cm_msg(MERROR, "db_open_database", "maximum number of clients exceeded");
01140 return DB_NO_SLOT;
01141 }
01142
01143
01144 _database[handle].client_index = i;
01145
01146
01147
01148
01149
01150 pheader->num_clients++;
01151 if (i + 1 > pheader->max_client_index)
01152 pheader->max_client_index = i + 1;
01153
01154
01155 pclient = &pheader->client[i];
01156
01157 memset(pclient, 0, sizeof(DATABASE_CLIENT));
01158
01159 strcpy(pclient->name, client_name);
01160 pclient->pid = ss_getpid();
01161 pclient->tid = ss_gettid();
01162 pclient->thandle = ss_getthandle();
01163 pclient->num_open_records = 0;
01164
01165 ss_suspend_get_port(&pclient->port);
01166
01167 pclient->last_activity = ss_millitime();
01168
01169 cm_get_watchdog_params(&call_watchdog, &timeout);
01170 pclient->watchdog_timeout = timeout;
01171
01172
01173 if (!db_validate_db(pheader)) {
01174
01175
01176
01177
01178
01179
01180
01181
01182 }
01183
01184
01185 _database[handle].database_data = _database[handle].database_header + 1;
01186 _database[handle].attached = TRUE;
01187 _database[handle].shm_handle = shm_handle;
01188 _database[handle].protect = FALSE;
01189
01190
01191 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE)
01192 _database[handle].index = rpc_get_server_acception();
01193 else
01194 _database[handle].index = ss_gettid();
01195
01196 *hDB = (handle + 1);
01197
01198
01199 ss_suspend_set_dispatch(CH_IPC, 0, (int (*)(void)) cm_dispatch_ipc);
01200
01201
01202
01203
01204 #ifdef ESRCH
01205
01206
01207 for (i = 0; i < MAX_CLIENTS; i++) {
01208 int k;
01209
01210 errno = 0;
01211 kill(pheader->client[i].pid, 0);
01212 if (errno == ESRCH) {
01213 cm_msg(MERROR, "db_open_database",
01214 "removing client %s, pid %d, index %d because the pid no longer exists",
01215 pheader->client[i].name, pheader->client[i].pid, i);
01216
01217
01218 for (k = 0; k < pheader->client[i].max_index; k++)
01219 if (pheader->client[i].open_record[k].handle) {
01220 pkey = (KEY *) ((char *) pheader +
01221 pheader->client[i].open_record[k].handle);
01222 if (pkey->notify_count > 0)
01223 pkey->notify_count--;
01224
01225 if (pheader->client[i].open_record[k].access_mode & MODE_WRITE)
01226 db_set_mode(handle + 1, pheader->client[i].open_record[k].handle,
01227 (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2);
01228 }
01229
01230
01231 memset(&(pheader->client[i]), 0, sizeof(DATABASE_CLIENT));
01232 }
01233 }
01234 #endif
01235
01236 db_unlock_database(handle + 1);
01237
01238 if (shm_created)
01239 return DB_CREATED;
01240 }
01241 #endif
01242
01243 return DB_SUCCESS;
01244 }
01245
01246
01247
01248
01249
01250
01251
01252 INT db_close_database(HNDLE hDB)
01253 {
01254 if (rpc_is_remote())
01255 return rpc_call(RPC_DB_CLOSE_DATABASE, hDB);
01256
01257 #ifdef LOCAL_ROUTINES
01258 else {
01259 DATABASE_HEADER *pheader;
01260 DATABASE_CLIENT *pclient;
01261 INT index, destroy_flag, i, j;
01262
01263 if (hDB > _database_entries || hDB <= 0) {
01264 cm_msg(MERROR, "db_close_database", "invalid database handle");
01265 return DB_INVALID_HANDLE;
01266 }
01267
01268
01269
01270
01271
01272
01273
01274
01275 db_lock_database(hDB);
01276
01277 index = _database[hDB - 1].client_index;
01278 pheader = _database[hDB - 1].database_header;
01279 pclient = &pheader->client[index];
01280
01281 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE &&
01282 _database[hDB - 1].index != rpc_get_server_acception()) {
01283 db_unlock_database(hDB);
01284 return DB_INVALID_HANDLE;
01285 }
01286
01287 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE &&
01288 _database[hDB - 1].index != ss_gettid()) {
01289 db_unlock_database(hDB);
01290 return DB_INVALID_HANDLE;
01291 }
01292
01293 if (!_database[hDB - 1].attached) {
01294 cm_msg(MERROR, "db_close_database", "invalid database handle");
01295 db_unlock_database(hDB);
01296 return DB_INVALID_HANDLE;
01297 }
01298
01299
01300 for (i = 0; i < pclient->max_index; i++)
01301 if (pclient->open_record[i].handle)
01302 db_remove_open_record(hDB, pclient->open_record[i].handle, FALSE);
01303
01304
01305 _database[hDB - 1].attached = FALSE;
01306
01307
01308 memset(&(pheader->client[index]), 0, sizeof(DATABASE_CLIENT));
01309
01310
01311 for (i = MAX_CLIENTS - 1; i >= 0; i--)
01312 if (pheader->client[i].pid != 0)
01313 break;
01314 pheader->max_client_index = i + 1;
01315
01316
01317 for (i = MAX_CLIENTS - 1, j = 0; i >= 0; i--)
01318 if (pheader->client[i].pid != 0)
01319 j++;
01320 pheader->num_clients = j;
01321
01322 destroy_flag = (pheader->num_clients == 0);
01323
01324
01325 ss_shm_flush(pheader->name, pheader,
01326 sizeof(DATABASE_HEADER) + 2 * pheader->data_size);
01327
01328
01329 ss_shm_close(pheader->name, pheader, _database[hDB - 1].shm_handle, destroy_flag);
01330
01331
01332 db_unlock_database(hDB);
01333
01334
01335 ss_mutex_delete(_database[hDB - 1].mutex, destroy_flag);
01336
01337
01338 if (hDB == _database_entries)
01339 _database_entries--;
01340
01341 if (_database_entries > 0)
01342 _database =
01343 (DATABASE *) realloc(_database, sizeof(DATABASE) * (_database_entries));
01344 else {
01345 free(_database);
01346 _database = NULL;
01347 }
01348
01349
01350 if (destroy_flag) {
01351 extern INT _mutex_elog, _mutex_alarm;
01352
01353 if (_mutex_elog)
01354 ss_mutex_delete(_mutex_elog, TRUE);
01355 if (_mutex_alarm)
01356 ss_mutex_delete(_mutex_alarm, TRUE);
01357 }
01358
01359 }
01360 #endif
01361
01362 return DB_SUCCESS;
01363 }
01364
01365
01366 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01367
01368
01369 INT db_flush_database(HNDLE hDB)
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 {
01390 if (rpc_is_remote())
01391 return rpc_call(RPC_DB_FLUSH_DATABASE, hDB);
01392
01393 #ifdef LOCAL_ROUTINES
01394 else {
01395 DATABASE_HEADER *pheader;
01396 DATABASE_CLIENT *pclient;
01397 INT index;
01398
01399 if (hDB > _database_entries || hDB <= 0) {
01400 cm_msg(MERROR, "db_close_database", "invalid database handle");
01401 return DB_INVALID_HANDLE;
01402 }
01403
01404
01405
01406
01407
01408
01409
01410 db_lock_database(hDB);
01411 index = _database[hDB - 1].client_index;
01412 pheader = _database[hDB - 1].database_header;
01413 pclient = &pheader->client[index];
01414
01415 if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE &&
01416 _database[hDB - 1].index != rpc_get_server_acception()) {
01417 db_unlock_database(hDB);
01418 return DB_INVALID_HANDLE;
01419 }
01420
01421 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE &&
01422 _database[hDB - 1].index != ss_gettid()) {
01423 db_unlock_database(hDB);
01424 return DB_INVALID_HANDLE;
01425 }
01426
01427 if (!_database[hDB - 1].attached) {
01428 cm_msg(MERROR, "db_close_database", "invalid database handle");
01429 db_unlock_database(hDB);
01430 return DB_INVALID_HANDLE;
01431 }
01432
01433
01434 ss_shm_flush(pheader->name, pheader,
01435 sizeof(DATABASE_HEADER) + 2 * pheader->data_size);
01436 db_unlock_database(hDB);
01437
01438 }
01439 #endif
01440
01441 return DB_SUCCESS;
01442 }
01443
01444
01445 INT db_close_all_databases(void)
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462 {
01463 INT status;
01464
01465 if (rpc_is_remote()) {
01466 status = rpc_call(RPC_DB_CLOSE_ALL_DATABASES);
01467 if (status != DB_SUCCESS)
01468 return status;
01469 }
01470 #ifdef LOCAL_ROUTINES
01471 {
01472 INT i;
01473
01474 for (i = _database_entries; i > 0; i--)
01475 db_close_database(i);
01476 }
01477 #endif
01478
01479 return db_close_all_records();
01480 }
01481
01482
01483 INT db_set_client_name(HNDLE hDB, char *client_name)
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 {
01503 if (rpc_is_remote())
01504 return rpc_call(RPC_DB_SET_CLIENT_NAME, hDB, client_name);
01505
01506 #ifdef LOCAL_ROUTINES
01507 {
01508 DATABASE_HEADER *pheader;
01509 DATABASE_CLIENT *pclient;
01510 INT index;
01511
01512 index = _database[hDB - 1].client_index;
01513 pheader = _database[hDB - 1].database_header;
01514 pclient = &pheader->client[index];
01515
01516 strcpy(pclient->name, client_name);
01517 }
01518 #endif
01519
01520 return DB_SUCCESS;
01521 }
01522
01523
01524 #endif
01525
01526
01527
01528
01529
01530
01531
01532 INT db_lock_database(HNDLE hDB)
01533 {
01534
01535 #ifdef LOCAL_ROUTINES
01536 if (hDB > _database_entries || hDB <= 0) {
01537 cm_msg(MERROR, "db_lock_database", "invalid database handle");
01538 return DB_INVALID_HANDLE;
01539 }
01540
01541 if (_database[hDB - 1].protect && _database[hDB - 1].database_header != NULL)
01542 cm_msg(MERROR, "db_lock_database", "internal error: DB already locked");
01543
01544 if (_database[hDB - 1].lock_cnt == 0)
01545 ss_mutex_wait_for(_database[hDB - 1].mutex, 0);
01546
01547 _database[hDB - 1].lock_cnt++;
01548
01549 if (_database[hDB - 1].protect) {
01550 if (_database[hDB - 1].database_header == NULL)
01551 ss_shm_unprotect(_database[hDB - 1].shm_handle,
01552 (void **) &_database[hDB - 1].database_header);
01553 }
01554 #endif
01555 return DB_SUCCESS;
01556 }
01557
01558
01559
01560
01561
01562
01563
01564 INT db_unlock_database(HNDLE hDB)
01565 {
01566
01567 #ifdef LOCAL_ROUTINES
01568 if (hDB > _database_entries || hDB <= 0) {
01569 cm_msg(MERROR, "db_unlock_database", "invalid database handle");
01570 return DB_INVALID_HANDLE;
01571 }
01572
01573 if (_database[hDB - 1].lock_cnt == 1)
01574 ss_mutex_release(_database[hDB - 1].mutex);
01575
01576 if (_database[hDB - 1].lock_cnt > 0)
01577 _database[hDB - 1].lock_cnt--;
01578
01579 if (_database[hDB - 1].protect) {
01580 ss_shm_protect(_database[hDB - 1].shm_handle, _database[hDB - 1].database_header);
01581 _database[hDB - 1].database_header = NULL;
01582 }
01583 #endif
01584 return DB_SUCCESS;
01585 }
01586
01587
01588
01589
01590
01591
01592
01593 INT db_protect_database(HNDLE hDB)
01594 {
01595 #ifdef LOCAL_ROUTINES
01596 if (hDB > _database_entries || hDB <= 0) {
01597 cm_msg(MERROR, "db_unlock_database", "invalid database handle");
01598 return DB_INVALID_HANDLE;
01599 }
01600
01601 _database[hDB - 1].protect = TRUE;
01602 ss_shm_protect(_database[hDB - 1].shm_handle, _database[hDB - 1].database_header);
01603 _database[hDB - 1].database_header = NULL;
01604 #endif
01605 return DB_SUCCESS;
01606 }
01607
01608
01609
01610 char *extract_key(char *key_list, char *key_name)
01611 {
01612 if (*key_list == '/')
01613 key_list++;
01614
01615 while (*key_list && *key_list != '/')
01616 *key_name++ = *key_list++;
01617 *key_name = 0;
01618
01619 return key_list;
01620 }
01621
01622 BOOL equal_ustring(char *str1, char *str2)
01623 {
01624 if (str1 == NULL && str2 != NULL)
01625 return FALSE;
01626 if (str1 != NULL && str2 == NULL)
01627 return FALSE;
01628 if (str1 == NULL && str2 == NULL)
01629 return TRUE;
01630
01631 while (*str1)
01632 if (toupper(*str1++) != toupper(*str2++))
01633 return FALSE;
01634
01635 if (*str2)
01636 return FALSE;
01637
01638 return TRUE;
01639 }
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650 INT db_create_key(HNDLE hDB, HNDLE hKey, char *key_name, DWORD type)
01651 {
01652 if (rpc_is_remote())
01653 return rpc_call(RPC_DB_CREATE_KEY, hDB, hKey, key_name, type);
01654
01655 #ifdef LOCAL_ROUTINES
01656 {
01657 DATABASE_HEADER *pheader;
01658 KEYLIST *pkeylist;
01659 KEY *pkey, *pprev_key, *pkeyparent;
01660 char *pkey_name, str[MAX_STRING_LENGTH];
01661 INT i;
01662
01663 if (hDB > _database_entries || hDB <= 0) {
01664 cm_msg(MERROR, "db_create_key", "invalid database handle");
01665 return DB_INVALID_HANDLE;
01666 }
01667
01668 if (!_database[hDB - 1].attached) {
01669 cm_msg(MERROR, "db_create_key", "invalid database handle");
01670 return DB_INVALID_HANDLE;
01671 }
01672
01673
01674 if (type >= TID_LAST) {
01675 cm_msg(MERROR, "db_create_key", "invalid key type %d", type);
01676 return DB_INVALID_PARAM;
01677 }
01678
01679
01680 db_lock_database(hDB);
01681
01682 pheader = _database[hDB - 1].database_header;
01683 if (!hKey)
01684 hKey = pheader->root_key;
01685 pkey = (KEY *) ((char *) pheader + hKey);
01686
01687
01688 if (!db_validate_hkey(pheader, hKey)) {
01689 db_unlock_database(hDB);
01690 return DB_INVALID_HANDLE;
01691 }
01692
01693 if (pkey->type != TID_KEY) {
01694 db_unlock_database(hDB);
01695 cm_msg(MERROR, "db_create_key", "key has no subkeys");
01696 return DB_NO_KEY;
01697 }
01698 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
01699
01700 pkey_name = key_name;
01701 do {
01702
01703 pkey_name = extract_key(pkey_name, str);
01704
01705
01706 if (strcmp(str, "..") == 0) {
01707 if (pkey->parent_keylist) {
01708 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
01709 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
01710 }
01711 continue;
01712 }
01713 if (strcmp(str, ".") == 0)
01714 continue;
01715
01716
01717 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
01718 pprev_key = NULL;
01719
01720 for (i = 0; i < pkeylist->num_keys; i++) {
01721 if (!db_validate_key_offset(pheader, pkey->next_key)) {
01722 cm_msg(MERROR, "db_create_key",
01723 "Warning: database corruption, key %s, next_key 0x%08X",
01724 key_name, pkey->next_key - sizeof(DATABASE_HEADER));
01725 db_unlock_database(hDB);
01726 return DB_CORRUPTED;
01727 }
01728
01729 if (equal_ustring(str, pkey->name))
01730 break;
01731
01732 pprev_key = pkey;
01733 pkey = (KEY *) ((char *) pheader + pkey->next_key);
01734 }
01735
01736 if (i == pkeylist->num_keys) {
01737
01738
01739
01740 pkeyparent = (KEY *) ((char *) pheader + pkeylist->parent);
01741 if (!(pkeyparent->access_mode & MODE_WRITE) ||
01742 (pkeyparent->access_mode & MODE_EXCLUSIVE)) {
01743 db_unlock_database(hDB);
01744 return DB_NO_ACCESS;
01745 }
01746
01747 pkeylist->num_keys++;
01748
01749 if (*pkey_name == '/' || type == TID_KEY) {
01750
01751 pkey = (KEY *) malloc_key(pheader, sizeof(KEY));
01752
01753 if (pkey == NULL) {
01754 db_unlock_database(hDB);
01755 cm_msg(MERROR, "db_create_key", "online database full");
01756 return DB_FULL;
01757 }
01758
01759
01760 if (pprev_key)
01761 pprev_key->next_key = (PTYPE) pkey - (PTYPE) pheader;
01762 else
01763 pkeylist->first_key = (PTYPE) pkey - (PTYPE) pheader;
01764
01765
01766 pkey->type = TID_KEY;
01767 pkey->num_values = 1;
01768 pkey->access_mode = MODE_READ | MODE_WRITE | MODE_DELETE;
01769 strcpy(pkey->name, str);
01770 pkey->parent_keylist = (PTYPE) pkeylist - (PTYPE) pheader;
01771
01772
01773 pkeylist = (KEYLIST *) malloc_key(pheader, sizeof(KEYLIST));
01774
01775 if (pkeylist == NULL) {
01776 db_unlock_database(hDB);
01777 cm_msg(MERROR, "db_create_key", "online database full");
01778 return DB_FULL;
01779 }
01780
01781
01782 pkey->data = (PTYPE) pkeylist - (PTYPE) pheader;
01783 pkey->item_size = sizeof(KEYLIST);
01784 pkey->total_size = sizeof(KEYLIST);
01785
01786 pkeylist->parent = (PTYPE) pkey - (PTYPE) pheader;
01787 pkeylist->num_keys = 0;
01788 pkeylist->first_key = 0;
01789 } else {
01790
01791 pkey = (KEY *) malloc_key(pheader, sizeof(KEY));
01792
01793 if (pkey == NULL) {
01794 db_unlock_database(hDB);
01795 cm_msg(MERROR, "db_create_key", "online database full");
01796 return DB_FULL;
01797 }
01798
01799
01800 if (pprev_key)
01801 pprev_key->next_key = (PTYPE) pkey - (PTYPE) pheader;
01802 else
01803 pkeylist->first_key = (PTYPE) pkey - (PTYPE) pheader;
01804
01805 pkey->type = type;
01806 pkey->num_values = 1;
01807 pkey->access_mode = MODE_READ | MODE_WRITE | MODE_DELETE;
01808 strcpy(pkey->name, str);
01809 pkey->parent_keylist = (PTYPE) pkeylist - (PTYPE) pheader;
01810
01811
01812 if (type != TID_STRING && type != TID_LINK) {
01813 pkey->item_size = rpc_tid_size(type);
01814 pkey->data = (PTYPE) malloc_data(pheader, pkey->item_size);
01815 pkey->total_size = pkey->item_size;
01816
01817 if (pkey->data == 0) {
01818 db_unlock_database(hDB);
01819 cm_msg(MERROR, "db_create_key", "online database full");
01820 return DB_FULL;
01821 }
01822
01823 pkey->data -= (PTYPE) pheader;
01824 } else {
01825
01826 pkey->item_size = 0;
01827 pkey->total_size = 0;
01828 pkey->data = 0;
01829 }
01830 }
01831 } else {
01832
01833
01834
01835 if (pkey->type == TID_LINK && pkey_name[0]) {
01836
01837 strcpy(str, (char *) pheader + pkey->data);
01838 if (str[strlen(str) - 1] == '/')
01839 str[strlen(str) - 1] = 0;
01840
01841
01842 strcat(str, pkey_name);
01843
01844 db_unlock_database(hDB);
01845
01846 return db_create_key(hDB, 0, str, type);
01847 }
01848
01849 if (!(*pkey_name == '/')) {
01850 if ((WORD) pkey->type != type)
01851 cm_msg(MERROR, "db_create_key", "redefinition of key type mismatch");
01852
01853 db_unlock_database(hDB);
01854 return DB_KEY_EXIST;
01855 }
01856
01857 if (pkey->type != TID_KEY) {
01858 db_unlock_database(hDB);
01859 cm_msg(MERROR, "db_create_key", "key used with value and as parent key");
01860 return DB_KEY_EXIST;
01861 }
01862
01863 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
01864 }
01865 } while (*pkey_name == '/');
01866
01867 db_unlock_database(hDB);
01868 }
01869 #endif
01870
01871 return DB_SUCCESS;
01872 }
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883 INT db_create_link(HNDLE hDB, HNDLE hKey, char *link_name, char *destination)
01884 {
01885 HNDLE hkey;
01886 int status;
01887
01888 if (rpc_is_remote())
01889 return rpc_call(RPC_DB_CREATE_LINK, hDB, hKey, link_name, destination);
01890
01891
01892 status = db_find_key(hDB, hKey, destination, &hkey);
01893 if (status != DB_SUCCESS) {
01894 cm_msg(MERROR, "db_create_link",
01895 "Link destination \"%s\" does not exist", destination);
01896 return DB_NO_KEY;
01897 }
01898
01899 return db_set_value(hDB, hKey, link_name, destination,
01900 strlen(destination) + 1, 1, TID_LINK);
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913 INT db_delete_key1(HNDLE hDB, HNDLE hKey, INT level, BOOL follow_links)
01914 {
01915 #ifdef LOCAL_ROUTINES
01916 {
01917 DATABASE_HEADER *pheader;
01918 KEYLIST *pkeylist;
01919 KEY *pkey, *pnext_key, *pkey_tmp;
01920 HNDLE hKeyLink;
01921 BOOL deny_delete;
01922 INT status;
01923
01924 if (hDB > _database_entries || hDB <= 0) {
01925 cm_msg(MERROR, "db_delete_key1", "invalid database handle");
01926 return DB_INVALID_HANDLE;
01927 }
01928
01929 if (!_database[hDB - 1].attached) {
01930 cm_msg(MERROR, "db_delete_key1", "invalid database handle");
01931 return DB_INVALID_HANDLE;
01932 }
01933
01934 if (hKey < sizeof(DATABASE_HEADER)) {
01935 cm_msg(MERROR, "db_delete_key1", "invalid key handle");
01936 return DB_INVALID_HANDLE;
01937 }
01938
01939
01940 if (level == 0)
01941 db_lock_database(hDB);
01942
01943 pheader = _database[hDB - 1].database_header;
01944
01945 pkey = (KEY *) ((char *) pheader + hKey);
01946
01947
01948 if (!db_validate_hkey(pheader, hKey)) {
01949 db_unlock_database(hDB);
01950 return DB_INVALID_HANDLE;
01951 }
01952
01953
01954 if (level == 0)
01955 do {
01956 if (pkey->notify_count) {
01957 db_unlock_database(hDB);
01958 return DB_OPEN_RECORD;
01959 }
01960
01961 if (pkey->parent_keylist == 0)
01962 break;
01963
01964 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
01965 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
01966 } while (TRUE);
01967
01968 pkey = (KEY *) ((char *) pheader + hKey);
01969 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
01970
01971 deny_delete = FALSE;
01972
01973
01974 if (pkey->type == TID_KEY && pkeylist->first_key) {
01975 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
01976
01977 do {
01978 pnext_key = (KEY *) (PTYPE) pkey->next_key;
01979
01980 status = db_delete_key1(hDB, (PTYPE) pkey - (PTYPE) pheader,
01981 level + 1, follow_links);
01982
01983 if (status == DB_NO_ACCESS)
01984 deny_delete = TRUE;
01985
01986 if (pnext_key)
01987 pkey = (KEY *) ((char *) pheader + (PTYPE) pnext_key);
01988 } while (pnext_key);
01989 }
01990
01991
01992 if (pkey->type == TID_LINK && follow_links) {
01993 status = db_find_key(hDB, 0, (char *) pheader + pkey->data, &hKeyLink);
01994 if (status == DB_SUCCESS && follow_links < 100)
01995 db_delete_key1(hDB, hKeyLink, level + 1, follow_links + 1);
01996
01997 if (follow_links == 100)
01998 cm_msg(MERROR, "db_delete_key1", "try to delete cyclic link");
01999 }
02000
02001 pkey = (KEY *) ((char *) pheader + hKey);
02002
02003
02004 if (pkey->parent_keylist == 0) {
02005 if (level == 0)
02006 db_unlock_database(hDB);
02007 return DB_SUCCESS;
02008 }
02009
02010
02011 if (hKey != pheader->root_key) {
02012 if (!(pkey->access_mode & MODE_DELETE) || deny_delete) {
02013 if (level == 0)
02014 db_unlock_database(hDB);
02015 return DB_NO_ACCESS;
02016 }
02017
02018 if (pkey->notify_count) {
02019 if (level == 0)
02020 db_unlock_database(hDB);
02021 return DB_OPEN_RECORD;
02022 }
02023
02024
02025 if (pkey->type == TID_KEY)
02026 free_key(pheader, (char *) pheader + pkey->data, pkey->total_size);
02027 else
02028 free_data(pheader, (char *) pheader + pkey->data, pkey->total_size);
02029
02030
02031 pnext_key = (KEY *) (PTYPE) pkey->next_key;
02032 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
02033
02034 if ((KEY *) ((char *) pheader + pkeylist->first_key) == pkey) {
02035
02036 pkeylist->first_key = (PTYPE) pnext_key;
02037 } else {
02038
02039 pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
02040 while ((KEY *) ((char *) pheader + pkey_tmp->next_key) != pkey)
02041 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
02042 pkey_tmp->next_key = (PTYPE) pnext_key;
02043 }
02044
02045
02046 free_key(pheader, pkey, sizeof(KEY));
02047 pkeylist->num_keys--;
02048 }
02049
02050 if (level == 0)
02051 db_unlock_database(hDB);
02052 }
02053 #endif
02054
02055 return DB_SUCCESS;
02056 }
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083 INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
02084 {
02085 if (rpc_is_remote())
02086 return rpc_call(RPC_DB_DELETE_KEY, hDB, hKey, follow_links);
02087
02088 return db_delete_key1(hDB, hKey, 0, follow_links);
02089 }
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116 INT db_find_key(HNDLE hDB, HNDLE hKey, char *key_name, HNDLE * subhKey)
02117 {
02118 if (rpc_is_remote())
02119 return rpc_call(RPC_DB_FIND_KEY, hDB, hKey, key_name, subhKey);
02120
02121 #ifdef LOCAL_ROUTINES
02122 {
02123 DATABASE_HEADER *pheader;
02124 KEYLIST *pkeylist;
02125 KEY *pkey;
02126 char *pkey_name, str[MAX_STRING_LENGTH];
02127 INT i, status;
02128
02129 *subhKey = 0;
02130
02131 if (hDB > _database_entries || hDB <= 0) {
02132 cm_msg(MERROR, "db_find_key", "invalid database handle");
02133 return DB_INVALID_HANDLE;
02134 }
02135
02136 if (!_database[hDB - 1].attached) {
02137 cm_msg(MERROR, "db_find_key", "invalid database handle");
02138 return DB_INVALID_HANDLE;
02139 }
02140
02141 db_lock_database(hDB);
02142
02143 pheader = _database[hDB - 1].database_header;
02144
02145 if (!hKey)
02146 hKey = pheader->root_key;
02147
02148 pkey = (KEY *) ((char *) pheader + hKey);
02149
02150
02151 if (!db_validate_hkey(pheader, hKey)) {
02152 db_unlock_database(hDB);
02153 return DB_INVALID_HANDLE;
02154 }
02155
02156 if (pkey->type != TID_KEY) {
02157 cm_msg(MERROR, "db_find_key", "key has no subkeys");
02158 *subhKey = 0;
02159 db_unlock_database(hDB);
02160 return DB_NO_KEY;
02161 }
02162 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02163
02164 if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
02165 if (!(pkey->access_mode & MODE_READ)) {
02166 *subhKey = 0;
02167 db_unlock_database(hDB);
02168 return DB_NO_ACCESS;
02169 }
02170
02171 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02172
02173 db_unlock_database(hDB);
02174 return DB_SUCCESS;
02175 }
02176
02177 pkey_name = key_name;
02178 do {
02179
02180 pkey_name = extract_key(pkey_name, str);
02181
02182
02183 if (strcmp(str, "..") == 0) {
02184 if (pkey->parent_keylist) {
02185 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
02186 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
02187 }
02188 continue;
02189 }
02190 if (strcmp(str, ".") == 0)
02191 continue;
02192
02193
02194 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
02195
02196 for (i = 0; i < pkeylist->num_keys; i++) {
02197 if (pkey->name[0] == 0 || !db_validate_key_offset(pheader, pkey->next_key)) {
02198 cm_msg(MERROR, "db_find_key",
02199 "Warning: database corruption, key %s, next_key 0x%08X",
02200 key_name, pkey->next_key - sizeof(DATABASE_HEADER));
02201 *subhKey = 0;
02202 db_unlock_database(hDB);
02203 return DB_CORRUPTED;
02204 }
02205
02206 if (equal_ustring(str, pkey->name))
02207 break;
02208
02209 pkey = (KEY *) ((char *) pheader + pkey->next_key);
02210 }
02211
02212 if (i == pkeylist->num_keys) {
02213 *subhKey = 0;
02214 db_unlock_database(hDB);
02215 return DB_NO_KEY;
02216 }
02217
02218
02219 if (pkey->type == TID_LINK) {
02220
02221 strcpy(str, (char *) pheader + pkey->data);
02222 if (str[strlen(str) - 1] == '/')
02223 str[strlen(str) - 1] = 0;
02224
02225
02226 if (pkey_name[0]) {
02227 strcat(str, pkey_name);
02228 db_unlock_database(hDB);
02229 return db_find_key(hDB, 0, str, subhKey);
02230 } else {
02231
02232 db_unlock_database(hDB);
02233 status = db_find_link(hDB, 0, str, subhKey);
02234 if (status == DB_NO_KEY)
02235 return DB_INVALID_LINK;
02236 return status;
02237 }
02238 }
02239
02240
02241 if (*pkey_name == '/') {
02242 if (pkey->type != TID_KEY) {
02243 *subhKey = 0;
02244 db_unlock_database(hDB);
02245 return DB_NO_KEY;
02246 }
02247 }
02248
02249
02250 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02251
02252 } while (*pkey_name == '/' && *(pkey_name + 1));
02253
02254 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02255
02256 db_unlock_database(hDB);
02257 }
02258 #endif
02259
02260 return DB_SUCCESS;
02261 }
02262
02263
02264 #ifndef DOXYGEN_SHOULD_SKIP_THIS
02265
02266
02267 INT db_find_key1(HNDLE hDB, HNDLE hKey, char *key_name, HNDLE * subhKey)
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289 {
02290 if (rpc_is_remote())
02291 return rpc_call(RPC_DB_FIND_KEY, hDB, hKey, key_name, subhKey);
02292
02293 #ifdef LOCAL_ROUTINES
02294 {
02295 DATABASE_HEADER *pheader;
02296 KEYLIST *pkeylist;
02297 KEY *pkey;
02298 char *pkey_name, str[MAX_STRING_LENGTH];
02299 INT i;
02300
02301 *subhKey = 0;
02302
02303 if (hDB > _database_entries || hDB <= 0) {
02304 cm_msg(MERROR, "db_find_key", "invalid database handle");
02305 return DB_INVALID_HANDLE;
02306 }
02307
02308 if (!_database[hDB - 1].attached) {
02309 cm_msg(MERROR, "db_find_key", "invalid database handle");
02310 return DB_INVALID_HANDLE;
02311 }
02312
02313 pheader = _database[hDB - 1].database_header;
02314 if (!hKey)
02315 hKey = pheader->root_key;
02316 pkey = (KEY *) ((char *) pheader + hKey);
02317
02318
02319 if (!db_validate_hkey(pheader, hKey)) {
02320 db_unlock_database(hDB);
02321 return DB_INVALID_HANDLE;
02322 }
02323
02324 if (pkey->type != TID_KEY) {
02325 cm_msg(MERROR, "db_find_key", "key has no subkeys");
02326 *subhKey = 0;
02327 return DB_NO_KEY;
02328 }
02329 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02330
02331 if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
02332 if (!(pkey->access_mode & MODE_READ)) {
02333 *subhKey = 0;
02334 return DB_NO_ACCESS;
02335 }
02336
02337 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02338
02339 return DB_SUCCESS;
02340 }
02341
02342 pkey_name = key_name;
02343 do {
02344
02345 pkey_name = extract_key(pkey_name, str);
02346
02347
02348 if (strcmp(str, "..") == 0) {
02349 if (pkey->parent_keylist) {
02350 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
02351 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
02352 }
02353 continue;
02354 }
02355 if (strcmp(str, ".") == 0)
02356 continue;
02357
02358
02359 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
02360
02361 for (i = 0; i < pkeylist->num_keys; i++) {
02362 if (equal_ustring(str, pkey->name))
02363 break;
02364
02365 pkey = (KEY *) ((char *) pheader + pkey->next_key);
02366 }
02367
02368 if (i == pkeylist->num_keys) {
02369 *subhKey = 0;
02370 return DB_NO_KEY;
02371 }
02372
02373
02374 if (pkey->type == TID_LINK) {
02375
02376 strcpy(str, (char *) pheader + pkey->data);
02377 if (str[strlen(str) - 1] == '/')
02378 str[strlen(str) - 1] = 0;
02379
02380
02381 if (pkey_name[0]) {
02382 strcat(str, pkey_name);
02383 return db_find_key1(hDB, 0, str, subhKey);
02384 } else {
02385
02386 return db_find_link1(hDB, 0, str, subhKey);
02387 }
02388 }
02389
02390
02391 if (*pkey_name == '/') {
02392 if (pkey->type != TID_KEY) {
02393 *subhKey = 0;
02394 db_unlock_database(hDB);
02395 return DB_NO_KEY;
02396 }
02397 }
02398
02399
02400 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02401
02402 } while (*pkey_name == '/' && *(pkey_name + 1));
02403
02404 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02405 }
02406 #endif
02407
02408 return DB_SUCCESS;
02409 }
02410
02411
02412 INT db_find_link(HNDLE hDB, HNDLE hKey, char *key_name, HNDLE * subhKey)
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438 {
02439 if (rpc_is_remote())
02440 return rpc_call(RPC_DB_FIND_LINK, hDB, hKey, key_name, subhKey);
02441
02442 #ifdef LOCAL_ROUTINES
02443 {
02444 DATABASE_HEADER *pheader;
02445 KEYLIST *pkeylist;
02446 KEY *pkey;
02447 char *pkey_name, str[MAX_STRING_LENGTH];
02448 INT i;
02449
02450 *subhKey = 0;
02451
02452 if (hDB > _database_entries || hDB <= 0) {
02453 cm_msg(MERROR, "db_find_link", "Invalid database handle");
02454 return DB_INVALID_HANDLE;
02455 }
02456
02457 if (!_database[hDB - 1].attached) {
02458 cm_msg(MERROR, "db_find_link", "invalid database handle");
02459 return DB_INVALID_HANDLE;
02460 }
02461
02462 db_lock_database(hDB);
02463
02464 pheader = _database[hDB - 1].database_header;
02465 if (!hKey)
02466 hKey = pheader->root_key;
02467 pkey = (KEY *) ((char *) pheader + hKey);
02468
02469
02470 if (!db_validate_hkey(pheader, hKey)) {
02471 db_unlock_database(hDB);
02472 return DB_INVALID_HANDLE;
02473 }
02474
02475 if (pkey->type != TID_KEY) {
02476 cm_msg(MERROR, "db_find_link", "key has no subkeys");
02477 db_unlock_database(hDB);
02478 return DB_NO_KEY;
02479 }
02480 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02481
02482 if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
02483 if (!(pkey->access_mode & MODE_READ)) {
02484 *subhKey = 0;
02485 db_unlock_database(hDB);
02486 return DB_NO_ACCESS;
02487 }
02488
02489 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02490
02491 db_unlock_database(hDB);
02492 return DB_SUCCESS;
02493 }
02494
02495 pkey_name = key_name;
02496 do {
02497
02498 pkey_name = extract_key(pkey_name, str);
02499
02500
02501 if (strcmp(str, "..") == 0) {
02502 if (pkey->parent_keylist) {
02503 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
02504 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
02505 }
02506 continue;
02507 }
02508 if (strcmp(str, ".") == 0)
02509 continue;
02510
02511
02512 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
02513
02514 for (i = 0; i < pkeylist->num_keys; i++) {
02515 if (!db_validate_key_offset(pheader, pkey->next_key)) {
02516 cm_msg(MERROR, "db_find_link",
02517 "Warning: database corruption, key \"%s\", next_key 0x%08X",
02518 key_name, pkey->next_key - sizeof(DATABASE_HEADER));
02519 *subhKey = 0;
02520 db_unlock_database(hDB);
02521 return DB_CORRUPTED;
02522 }
02523
02524 if (equal_ustring(str, pkey->name))
02525 break;
02526
02527 pkey = (KEY *) ((char *) pheader + pkey->next_key);
02528 }
02529
02530 if (i == pkeylist->num_keys) {
02531 *subhKey = 0;
02532 db_unlock_database(hDB);
02533 return DB_NO_KEY;
02534 }
02535
02536
02537 if (pkey->type == TID_LINK && *pkey_name == '/') {
02538
02539 strcpy(str, (char *) pheader + pkey->data);
02540 if (str[strlen(str) - 1] == '/')
02541 str[strlen(str) - 1] = 0;
02542
02543
02544 strcat(str, pkey_name);
02545 db_unlock_database(hDB);
02546 return db_find_link(hDB, 0, str, subhKey);
02547 }
02548
02549
02550 if ((*pkey_name == '/')) {
02551 if (pkey->type != TID_KEY) {
02552 *subhKey = 0;
02553 db_unlock_database(hDB);
02554 return DB_NO_KEY;
02555 }
02556 }
02557
02558
02559 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02560
02561 } while (*pkey_name == '/' && *(pkey_name + 1));
02562
02563 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02564
02565 db_unlock_database(hDB);
02566 }
02567 #endif
02568
02569 return DB_SUCCESS;
02570 }
02571
02572
02573 INT db_find_link1(HNDLE hDB, HNDLE hKey, char *key_name, HNDLE * subhKey)
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595 {
02596 if (rpc_is_remote())
02597 return rpc_call(RPC_DB_FIND_LINK, hDB, hKey, key_name, subhKey);
02598
02599 #ifdef LOCAL_ROUTINES
02600 {
02601 DATABASE_HEADER *pheader;
02602 KEYLIST *pkeylist;
02603 KEY *pkey;
02604 char *pkey_name, str[MAX_STRING_LENGTH];
02605 INT i;
02606
02607 *subhKey = 0;
02608
02609 if (hDB > _database_entries || hDB <= 0) {
02610 cm_msg(MERROR, "db_find_link", "Invalid database handle");
02611 return DB_INVALID_HANDLE;
02612 }
02613
02614 if (!_database[hDB - 1].attached) {
02615 cm_msg(MERROR, "db_find_link", "invalid database handle");
02616 return DB_INVALID_HANDLE;
02617 }
02618
02619 pheader = _database[hDB - 1].database_header;
02620 if (!hKey)
02621 hKey = pheader->root_key;
02622 pkey = (KEY *) ((char *) pheader + hKey);
02623
02624
02625 if (!db_validate_hkey(pheader, hKey)) {
02626 db_unlock_database(hDB);
02627 return DB_INVALID_HANDLE;
02628 }
02629
02630 if (pkey->type != TID_KEY) {
02631 cm_msg(MERROR, "db_find_link", "key has no subkeys");
02632 return DB_NO_KEY;
02633 }
02634 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02635
02636 if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
02637 if (!(pkey->access_mode & MODE_READ)) {
02638 *subhKey = 0;
02639 return DB_NO_ACCESS;
02640 }
02641
02642 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02643
02644 return DB_SUCCESS;
02645 }
02646
02647 pkey_name = key_name;
02648 do {
02649
02650 pkey_name = extract_key(pkey_name, str);
02651
02652
02653 if (strcmp(str, "..") == 0) {
02654 if (pkey->parent_keylist) {
02655 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
02656 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
02657 }
02658 continue;
02659 }
02660 if (strcmp(str, ".") == 0)
02661 continue;
02662
02663
02664 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
02665
02666 for (i = 0; i < pkeylist->num_keys; i++) {
02667 if (!db_validate_key_offset(pheader, pkey->next_key)) {
02668 cm_msg(MERROR, "db_find_link1",
02669 "Warning: database corruption, key \"%s\", next_key 0x%08X",
02670 key_name, pkey->next_key - sizeof(DATABASE_HEADER));
02671 *subhKey = 0;
02672 return DB_CORRUPTED;
02673 }
02674
02675 if (equal_ustring(str, pkey->name))
02676 break;
02677
02678 pkey = (KEY *) ((char *) pheader + pkey->next_key);
02679 }
02680
02681 if (i == pkeylist->num_keys) {
02682 *subhKey = 0;
02683 return DB_NO_KEY;
02684 }
02685
02686
02687 if (pkey->type == TID_LINK && *pkey_name == '/') {
02688
02689 strcpy(str, (char *) pheader + pkey->data);
02690 if (str[strlen(str) - 1] == '/')
02691 str[strlen(str) - 1] = 0;
02692
02693
02694 strcat(str, pkey_name);
02695 return db_find_link1(hDB, 0, str, subhKey);
02696 }
02697
02698
02699 if ((*pkey_name == '/')) {
02700 if (pkey->type != TID_KEY) {
02701 *subhKey = 0;
02702 return DB_NO_KEY;
02703 }
02704 }
02705
02706
02707 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02708
02709 } while (*pkey_name == '/' && *(pkey_name + 1));
02710
02711 *subhKey = (PTYPE) pkey - (PTYPE) pheader;
02712 }
02713 #endif
02714
02715 return DB_SUCCESS;
02716 }
02717
02718
02719 INT db_scan_tree(HNDLE hDB, HNDLE hKey, INT level,
02720 INT(*callback) (HNDLE, HNDLE, KEY *, INT, void *), void *info)
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747 {
02748 HNDLE hSubkey;
02749 KEY key;
02750 INT i, status;
02751
02752 status = db_get_key(hDB, hKey, &key);
02753 if (status != DB_SUCCESS)
02754 return status;
02755
02756 status = callback(hDB, hKey, &key, level, info);
02757 if (status == 0)
02758 return status;
02759
02760 if (key.type == TID_KEY) {
02761 for (i = 0;; i++) {
02762 db_enum_key(hDB, hKey, i, &hSubkey);
02763
02764 if (!hSubkey)
02765 break;
02766
02767 db_scan_tree(hDB, hSubkey, level + 1, callback, info);
02768 }
02769 }
02770
02771 return DB_SUCCESS;
02772 }
02773
02774
02775 INT db_scan_tree_link(HNDLE hDB, HNDLE hKey, INT level,
02776 void (*callback) (HNDLE, HNDLE, KEY *, INT, void *), void *info)
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804 {
02805 HNDLE hSubkey;
02806 KEY key;
02807 INT i, status;
02808
02809 status = db_get_key(hDB, hKey, &key);
02810 if (status != DB_SUCCESS)
02811 return status;
02812
02813 callback(hDB, hKey, &key, level, info);
02814
02815 if (key.type == TID_KEY) {
02816 for (i = 0;; i++) {
02817 db_enum_link(hDB, hKey, i, &hSubkey);
02818
02819 if (!hSubkey)
02820 break;
02821
02822 db_scan_tree_link(hDB, hSubkey, level + 1, callback, info);
02823 }
02824 }
02825
02826 return DB_SUCCESS;
02827 }
02828
02829
02830 INT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853 {
02854 if (rpc_is_remote())
02855 return rpc_call(RPC_DB_GET_PATH, hDB, hKey, path, buf_size);
02856
02857 #ifdef LOCAL_ROUTINES
02858 {
02859 DATABASE_HEADER *pheader;
02860 KEYLIST *pkeylist;
02861 KEY *pkey;
02862 char str[MAX_ODB_PATH];
02863
02864 if (hDB > _database_entries || hDB <= 0) {
02865 cm_msg(MERROR, "db_get_path", "invalid database handle");
02866 return DB_INVALID_HANDLE;
02867 }
02868
02869 if (!_database[hDB - 1].attached) {
02870 cm_msg(MERROR, "db_get_path", "invalid database handle");
02871 return DB_INVALID_HANDLE;
02872 }
02873
02874 db_lock_database(hDB);
02875
02876 pheader = _database[hDB - 1].database_header;
02877 if (!hKey)
02878 hKey = pheader->root_key;
02879 pkey = (KEY *) ((char *) pheader + hKey);
02880
02881
02882 if (!db_validate_hkey(pheader, hKey)) {
02883 db_unlock_database(hDB);
02884 return DB_INVALID_HANDLE;
02885 }
02886
02887 if (hKey == pheader->root_key) {
02888 strcpy(path, "/");
02889 db_unlock_database(hDB);
02890 return DB_SUCCESS;
02891 }
02892
02893 *path = 0;
02894 do {
02895
02896 strcpy(str, path);
02897 strcpy(path, "/");
02898 strcat(path, pkey->name);
02899
02900 if (strlen(path) + strlen(str) + 1 > (DWORD) buf_size) {
02901 *path = 0;
02902 db_unlock_database(hDB);
02903 return DB_NO_MEMORY;
02904 }
02905 strcat(path, str);
02906
02907
02908 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
02909 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
02910 } while (pkey->parent_keylist);
02911
02912 db_unlock_database(hDB);
02913 }
02914 #endif
02915
02916 return DB_SUCCESS;
02917 }
02918
02919
02920 void db_find_open_records(HNDLE hDB, HNDLE hKey, KEY * key, INT level, void *result)
02921 {
02922 #ifdef LOCAL_ROUTINES
02923 DATABASE_HEADER *pheader;
02924 DATABASE_CLIENT *pclient;
02925 INT i, j;
02926 char line[256], str[80];
02927
02928
02929 if (key->notify_count) {
02930 db_get_path(hDB, hKey, str, sizeof(str));
02931 sprintf(line, "%s open %d times by ", str, key->notify_count);
02932
02933 db_lock_database(hDB);
02934 pheader = _database[hDB - 1].database_header;
02935
02936 for (i = 0; i < pheader->max_client_index; i++) {
02937 pclient = &pheader->client[i];
02938 for (j = 0; j < pclient->max_index; j++)
02939 if (pclient->open_record[j].handle == hKey)
02940 sprintf(line + strlen(line), "%s ", pclient->name);
02941 }
02942 strcat(line, "\n");
02943 strcat((char *) result, line);
02944
02945 db_unlock_database(hDB);
02946 }
02947 #endif
02948 }
02949
02950 void db_fix_open_records(HNDLE hDB, HNDLE hKey, KEY * key, INT level, void *result)
02951 {
02952 #ifdef LOCAL_ROUTINES
02953 DATABASE_HEADER *pheader;
02954 DATABASE_CLIENT *pclient;
02955 INT i, j;
02956 char str[256];
02957 KEY *pkey;
02958
02959
02960 if (key->notify_count) {
02961 db_lock_database(hDB);
02962 pheader = _database[hDB - 1].database_header;
02963
02964 for (i = 0; i < pheader->max_client_index; i++) {
02965 pclient = &pheader->client[i];
02966 for (j = 0; j < pclient->max_index; j++)
02967 if (pclient->open_record[j].handle == hKey)
02968 break;
02969 if (j < pclient->max_index)
02970 break;
02971 }
02972 if (i == pheader->max_client_index) {
02973 db_get_path(hDB, hKey, str, sizeof(str));
02974 strcat(str, " fixed\n");
02975 strcat((char *) result, str);
02976
02977
02978 pkey = (KEY *) ((char *) pheader + hKey);
02979 pkey->notify_count = 0;
02980 }
02981
02982 db_unlock_database(hDB);
02983 }
02984 #endif
02985 }
02986
02987 INT db_get_open_records(HNDLE hDB, HNDLE hKey, char *str, INT buf_size, BOOL fix)
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009 {
03010 str[0] = 0;
03011
03012 if (rpc_is_remote())
03013 return rpc_call(RPC_DB_GET_OPEN_RECORDS, hDB, hKey, str, buf_size);
03014
03015 if (fix)
03016 db_scan_tree_link(hDB, hKey, 0, db_fix_open_records, str);
03017 else
03018 db_scan_tree_link(hDB, hKey, 0, db_find_open_records, str);
03019
03020 return DB_SUCCESS;
03021 }
03022
03023
03024 #endif
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051 INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, char *key_name, void *data,
03052 INT data_size, INT num_values, DWORD type)
03053 {
03054 if (rpc_is_remote())
03055 return rpc_call(RPC_DB_SET_VALUE, hDB, hKeyRoot, key_name,
03056 data, data_size, num_values, type);
03057
03058 #ifdef LOCAL_ROUTINES
03059 {
03060 DATABASE_HEADER *pheader;
03061 KEY *pkey;
03062 HNDLE hKey;
03063 INT status;
03064
03065 if (num_values == 0)
03066 return DB_INVALID_PARAM;
03067
03068 status = db_find_key(hDB, hKeyRoot, key_name, &hKey);
03069 if (status == DB_NO_KEY) {
03070 db_create_key(hDB, hKeyRoot, key_name, type);
03071 status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
03072 }
03073
03074 if (status != DB_SUCCESS)
03075 return status;
03076
03077 db_lock_database(hDB);
03078 pheader = _database[hDB - 1].database_header;
03079
03080
03081 pkey = (KEY *) ((char *) pheader + hKey);
03082
03083
03084 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
03085 db_unlock_database(hDB);
03086 return DB_NO_ACCESS;
03087 }
03088
03089 if (pkey->type != type) {
03090 db_unlock_database(hDB);
03091 cm_msg(MERROR, "db_set_value", "\"%s\" is of type %s, not %s",
03092 key_name, rpc_tid_name(pkey->type), rpc_tid_name(type));
03093 return DB_TYPE_MISMATCH;
03094 }
03095
03096
03097 if (pkey->type == TID_KEY) {
03098 db_unlock_database(hDB);
03099 cm_msg(MERROR, "db_set_value", "key cannot contain data");
03100 return DB_TYPE_MISMATCH;
03101 }
03102
03103 if (data_size == 0) {
03104 db_unlock_database(hDB);
03105 cm_msg(MERROR, "db_set_value", "zero data size not allowed");
03106 return DB_TYPE_MISMATCH;
03107 }
03108
03109 if (type != TID_STRING && type != TID_LINK &&
03110 data_size != rpc_tid_size(type) * num_values) {
03111 db_unlock_database(hDB);
03112 cm_msg(MERROR, "db_set_value",
03113 "data_size (%d) does not match num_values (%d)", data_size, num_values);
03114 return DB_TYPE_MISMATCH;
03115 }
03116
03117
03118 if (pkey->total_size < data_size) {
03119 pkey->data =
03120 (PTYPE) realloc_data(pheader, (char *) pheader + pkey->data,
03121 pkey->total_size, data_size);
03122
03123 if (pkey->data == 0) {
03124 db_unlock_database(hDB);
03125 cm_msg(MERROR, "db_set_value", "online database full");
03126 return DB_FULL;
03127 }
03128
03129 pkey->data -= (PTYPE) pheader;
03130 pkey->total_size = data_size;
03131 }
03132
03133
03134 pkey->num_values = num_values;
03135
03136 if (type == TID_STRING || type == TID_LINK)
03137 pkey->item_size = data_size / num_values;
03138 else
03139 pkey->item_size = rpc_tid_size(type);
03140
03141
03142 memcpy((char *) pheader + pkey->data, data, data_size);
03143
03144
03145 pkey->last_written = ss_time();
03146
03147 db_notify_clients(hDB, hKey, TRUE);
03148 db_unlock_database(hDB);
03149
03150 }
03151 #endif
03152
03153 return DB_SUCCESS;
03154 }
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184 INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, char *key_name, void *data,
03185 INT * buf_size, DWORD type, BOOL create)
03186 {
03187 if (rpc_is_remote())
03188 return rpc_call(RPC_DB_GET_VALUE, hDB, hKeyRoot, key_name,
03189 data, buf_size, type, create);
03190
03191 #ifdef LOCAL_ROUTINES
03192 {
03193 DATABASE_HEADER *pheader;
03194 HNDLE hkey;
03195 KEY *pkey;
03196 INT status, size;
03197 char path[256];
03198
03199 if (hDB > _database_entries || hDB <= 0) {
03200 cm_msg(MERROR, "db_get_value", "invalid database handle");
03201 return DB_INVALID_HANDLE;
03202 }
03203
03204 if (!_database[hDB - 1].attached) {
03205 cm_msg(MERROR, "db_get_value", "invalid database handle");
03206 return DB_INVALID_HANDLE;
03207 }
03208
03209 status = db_find_key(hDB, hKeyRoot, key_name, &hkey);
03210 if (status == DB_NO_KEY) {
03211 if (create) {
03212 db_create_key(hDB, hKeyRoot, key_name, type);
03213 status = db_find_key(hDB, hKeyRoot, key_name, &hkey);
03214 if (status != DB_SUCCESS)
03215 return status;
03216
03217
03218 if (type == TID_STRING || type == TID_LINK)
03219 size = *buf_size;
03220 else
03221 size = rpc_tid_size(type);
03222
03223 if (size == 0)
03224 return DB_TYPE_MISMATCH;
03225
03226
03227 status = db_set_value(hDB, hKeyRoot, key_name, data,
03228 *buf_size, *buf_size / size, type);
03229 } else
03230 return DB_NO_KEY;
03231 }
03232
03233 if (status != DB_SUCCESS)
03234 return status;
03235
03236
03237 db_lock_database(hDB);
03238 pheader = _database[hDB - 1].database_header;
03239
03240
03241 pkey = (KEY *) ((char *) pheader + hkey);
03242
03243
03244 if (pkey->type != (type)) {
03245 db_unlock_database(hDB);
03246 cm_msg(MERROR, "db_get_value", "\"%s\" is of type %s, not %s",
03247 key_name, rpc_tid_name(pkey->type), rpc_tid_name(type));
03248 return DB_TYPE_MISMATCH;
03249 }
03250
03251
03252 if (!(pkey->access_mode & MODE_READ)) {
03253 db_unlock_database(hDB);
03254 cm_msg(MERROR, "db_get_value", "%s has no read access", key_name);
03255 return DB_NO_ACCESS;
03256 }
03257
03258
03259 if (pkey->num_values * pkey->item_size > *buf_size) {
03260 memcpy(data, (char *) pheader + pkey->data, *buf_size);
03261 db_unlock_database(hDB);
03262 db_get_path(hDB, hkey, path, sizeof(path));
03263 cm_msg(MERROR, "db_get_value",
03264 "buffer too small, data truncated for key \"%s\"", path);
03265 return DB_TRUNCATED;
03266 }
03267
03268
03269 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
03270 *buf_size = pkey->num_values * pkey->item_size;
03271
03272 db_unlock_database(hDB);
03273 }
03274 #endif
03275
03276 return DB_SUCCESS;
03277 }
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313 INT db_enum_key(HNDLE hDB, HNDLE hKey, INT index, HNDLE * subkey_handle)
03314 {
03315 if (rpc_is_remote())
03316 return rpc_call(RPC_DB_ENUM_KEY, hDB, hKey, index, subkey_handle);
03317
03318 #ifdef LOCAL_ROUTINES
03319 {
03320 DATABASE_HEADER *pheader;
03321 KEYLIST *pkeylist;
03322 KEY *pkey;
03323 INT i;
03324 char str[256];
03325 HNDLE parent;
03326
03327 if (hDB > _database_entries || hDB <= 0) {
03328 cm_msg(MERROR, "db_enum_key", "invalid database handle");
03329 return DB_INVALID_HANDLE;
03330 }
03331
03332 if (!_database[hDB - 1].attached) {
03333 cm_msg(MERROR, "db_enum_key", "invalid database handle");
03334 return DB_INVALID_HANDLE;
03335 }
03336
03337 *subkey_handle = 0;
03338
03339
03340 db_lock_database(hDB);
03341
03342 pheader = _database[hDB - 1].database_header;
03343 if (!hKey)
03344 hKey = pheader->root_key;
03345 pkey = (KEY *) ((char *) pheader + hKey);
03346
03347
03348 if (!db_validate_hkey(pheader, hKey)) {
03349 db_unlock_database(hDB);
03350 return DB_INVALID_HANDLE;
03351 }
03352
03353 if (pkey->type != TID_KEY) {
03354 db_unlock_database(hDB);
03355 return DB_NO_MORE_SUBKEYS;
03356 }
03357 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
03358
03359 if (index >= pkeylist->num_keys) {
03360 db_unlock_database(hDB);
03361 return DB_NO_MORE_SUBKEYS;
03362 }
03363
03364 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
03365 for (i = 0; i < index; i++)
03366 pkey = (KEY *) ((char *) pheader + pkey->next_key);
03367
03368
03369 if (pkey->type == TID_LINK) {
03370 strcpy(str, (char *) pheader + pkey->data);
03371
03372 if (*str == '/') {
03373
03374 db_unlock_database(hDB);
03375 return db_find_key(hDB, 0, str, subkey_handle);
03376 } else {
03377
03378 if (pkey->parent_keylist) {
03379 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
03380 parent = pkeylist->parent;
03381 db_unlock_database(hDB);
03382 return db_find_key(hDB, parent, str, subkey_handle);
03383 } else {
03384 db_unlock_database(hDB);
03385 return db_find_key(hDB, 0, str, subkey_handle);
03386 }
03387 }
03388 }
03389
03390 *subkey_handle = (PTYPE) pkey - (PTYPE) pheader;
03391 db_unlock_database(hDB);
03392 }
03393 #endif
03394
03395 return DB_SUCCESS;
03396 }
03397
03398
03399 #ifndef DOXYGEN_SHOULD_SKIP_THIS
03400
03401
03402
03403 INT db_enum_link(HNDLE hDB, HNDLE hKey, INT index, HNDLE * subkey_handle)
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429 {
03430 if (rpc_is_remote())
03431 return rpc_call(RPC_DB_ENUM_LINK, hDB, hKey, index, subkey_handle);
03432
03433 #ifdef LOCAL_ROUTINES
03434 {
03435 DATABASE_HEADER *pheader;
03436 KEYLIST *pkeylist;
03437 KEY *pkey;
03438 INT i;
03439
03440 if (hDB > _database_entries || hDB <= 0) {
03441 cm_msg(MERROR, "db_enum_link", "invalid database handle");
03442 return DB_INVALID_HANDLE;
03443 }
03444
03445 if (!_database[hDB - 1].attached) {
03446 cm_msg(MERROR, "db_enum_link", "invalid database handle");
03447 return DB_INVALID_HANDLE;
03448 }
03449
03450 *subkey_handle = 0;
03451
03452
03453 db_lock_database(hDB);
03454
03455 pheader = _database[hDB - 1].database_header;
03456 if (!hKey)
03457 hKey = pheader->root_key;
03458 pkey = (KEY *) ((char *) pheader + hKey);
03459
03460
03461 if (!db_validate_hkey(pheader, hKey)) {
03462 db_unlock_database(hDB);
03463 return DB_INVALID_HANDLE;
03464 }
03465
03466 if (pkey->type != TID_KEY) {
03467 db_unlock_database(hDB);
03468 return DB_NO_MORE_SUBKEYS;
03469 }
03470 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
03471
03472 if (index >= pkeylist->num_keys) {
03473 db_unlock_database(hDB);
03474 return DB_NO_MORE_SUBKEYS;
03475 }
03476
03477 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
03478 for (i = 0; i < index; i++)
03479 pkey = (KEY *) ((char *) pheader + pkey->next_key);
03480
03481 *subkey_handle = (PTYPE) pkey - (PTYPE) pheader;
03482 db_unlock_database(hDB);
03483 }
03484 #endif
03485
03486 return DB_SUCCESS;
03487 }
03488
03489
03490 INT db_get_next_link(HNDLE hDB, HNDLE hKey, HNDLE * subkey_handle)
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512 {
03513 if (rpc_is_remote())
03514 return rpc_call(RPC_DB_GET_NEXT_LINK, hDB, hKey, subkey_handle);
03515
03516 #ifdef LOCAL_ROUTINES
03517 {
03518 DATABASE_HEADER *pheader;
03519 KEYLIST *pkeylist;
03520 KEY *pkey;
03521 INT descent;
03522
03523 if (hDB > _database_entries || hDB <= 0) {
03524 cm_msg(MERROR, "db_enum_link", "invalid database handle");
03525 return DB_INVALID_HANDLE;
03526 }
03527
03528 if (!_database[hDB - 1].attached) {
03529 cm_msg(MERROR, "db_enum_link", "invalid database handle");
03530 return DB_INVALID_HANDLE;
03531 }
03532
03533 *subkey_handle = 0;
03534
03535
03536 db_lock_database(hDB);
03537
03538 pheader = _database[hDB - 1].database_header;
03539 if (!hKey)
03540 hKey = pheader->root_key;
03541 pkey = (KEY *) ((char *) pheader + hKey);
03542
03543
03544 if (!db_validate_hkey(pheader, hKey)) {
03545 db_unlock_database(hDB);
03546 return DB_INVALID_HANDLE;
03547 }
03548
03549 descent = TRUE;
03550 do {
03551 if (pkey->type != TID_KEY || !descent) {
03552 if (pkey->next_key) {
03553
03554 pkey = (KEY *) ((char *) pheader + pkey->next_key);
03555
03556 if (pkey->type != TID_KEY) {
03557 *subkey_handle = (PTYPE) pkey - (PTYPE) pheader;
03558 db_unlock_database(hDB);
03559 return DB_SUCCESS;
03560 }
03561
03562
03563 descent = TRUE;
03564 } else {
03565 if (pkey->parent_keylist == 0) {
03566
03567 db_unlock_database(hDB);
03568 return DB_NO_MORE_SUBKEYS;
03569 }
03570
03571
03572 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
03573
03574 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
03575 descent = FALSE;
03576 }
03577 } else {
03578 if (descent) {
03579
03580 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
03581
03582 if (pkeylist->num_keys == 0) {
03583
03584 descent = FALSE;
03585 } else {
03586
03587 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
03588
03589 if (pkey->type != TID_KEY) {
03590 *subkey_handle = (PTYPE) pkey - (PTYPE) pheader;
03591 db_unlock_database(hDB);
03592 return DB_SUCCESS;
03593 }
03594 }
03595 }
03596 }
03597
03598 } while (TRUE);
03599 }
03600 #endif
03601
03602 return DB_SUCCESS;
03603 }
03604
03605
03606 #endif
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645 INT db_get_key(HNDLE hDB, HNDLE hKey, KEY * key)
03646 {
03647 if (rpc_is_remote())
03648 return rpc_call(RPC_DB_GET_KEY, hDB, hKey, key);
03649
03650 #ifdef LOCAL_ROUTINES
03651 {
03652 DATABASE_HEADER *pheader;
03653 KEY *pkey;
03654
03655 if (hDB > _database_entries || hDB <= 0) {
03656 cm_msg(MERROR, "db_get_key", "invalid database handle");
03657 return DB_INVALID_HANDLE;
03658 }
03659
03660 if (!_database[hDB - 1].attached) {
03661 cm_msg(MERROR, "db_get_key", "invalid database handle");
03662 return DB_INVALID_HANDLE;
03663 }
03664
03665 if (hKey < sizeof(DATABASE_HEADER)) {
03666 cm_msg(MERROR, "db_get_key", "invalid key handle");
03667 return DB_INVALID_HANDLE;
03668 }
03669
03670 db_lock_database(hDB);
03671
03672 pheader = _database[hDB - 1].database_header;
03673 pkey = (KEY *) ((char *) pheader + hKey);
03674
03675
03676 if (!db_validate_hkey(pheader, hKey)) {
03677 db_unlock_database(hDB);
03678 return DB_INVALID_HANDLE;
03679 }
03680
03681 if (!pkey->type) {
03682 db_unlock_database(hDB);
03683 cm_msg(MERROR, "db_get_key", "invalid key");
03684 return DB_INVALID_HANDLE;
03685 }
03686
03687 memcpy(key, pkey, sizeof(KEY));
03688
03689 db_unlock_database(hDB);
03690
03691 }
03692 #endif
03693
03694 return DB_SUCCESS;
03695 }
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705 INT db_get_key_time(HNDLE hDB, HNDLE hKey, DWORD * delta)
03706 {
03707 if (rpc_is_remote())
03708 return rpc_call(RPC_DB_GET_KEY_TIME, hDB, hKey, delta);
03709
03710 #ifdef LOCAL_ROUTINES
03711 {
03712 DATABASE_HEADER *pheader;
03713 KEY *pkey;
03714
03715 if (hDB > _database_entries || hDB <= 0) {
03716 cm_msg(MERROR, "db_get_key", "invalid database handle");
03717 return DB_INVALID_HANDLE;
03718 }
03719
03720 if (!_database[hDB - 1].attached) {
03721 cm_msg(MERROR, "db_get_key", "invalid database handle");
03722 return DB_INVALID_HANDLE;
03723 }
03724
03725 if (hKey < sizeof(DATABASE_HEADER)) {
03726 cm_msg(MERROR, "db_get_key", "invalid key handle");
03727 return DB_INVALID_HANDLE;
03728 }
03729
03730 db_lock_database(hDB);
03731
03732 pheader = _database[hDB - 1].database_header;
03733 pkey = (KEY *) ((char *) pheader + hKey);
03734
03735
03736 if (!db_validate_hkey(pheader, hKey)) {
03737 db_unlock_database(hDB);
03738 return DB_INVALID_HANDLE;
03739 }
03740
03741 *delta = ss_time() - pkey->last_written;
03742
03743 db_unlock_database(hDB);
03744
03745 }
03746 #endif
03747
03748 return DB_SUCCESS;
03749 }
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763 INT db_get_key_info(HNDLE hDB, HNDLE hKey, char *name, INT name_size,
03764 INT * type, INT * num_values, INT * item_size)
03765 {
03766 if (rpc_is_remote())
03767 return rpc_call(RPC_DB_GET_KEY_INFO, hDB, hKey, name, name_size,
03768 type, num_values, item_size);
03769
03770 #ifdef LOCAL_ROUTINES
03771 {
03772 DATABASE_HEADER *pheader;
03773 KEY *pkey;
03774 KEYLIST *pkeylist;
03775
03776 if (hDB > _database_entries || hDB <= 0) {
03777 cm_msg(MERROR, "db_get_key_info", "invalid database handle");
03778 return DB_INVALID_HANDLE;
03779 }
03780
03781 if (!_database[hDB - 1].attached) {
03782 cm_msg(MERROR, "db_get_key_info", "invalid database handle");
03783 return DB_INVALID_HANDLE;
03784 }
03785
03786 if (hKey < sizeof(DATABASE_HEADER)) {
03787 cm_msg(MERROR, "db_get_key_info", "invalid key handle");
03788 return DB_INVALID_HANDLE;
03789 }
03790
03791 db_lock_database(hDB);
03792
03793 pheader = _database[hDB - 1].database_header;
03794 pkey = (KEY *) ((char *) pheader + hKey);
03795
03796
03797 if (!db_validate_hkey(pheader, hKey)) {
03798 db_unlock_database(hDB);
03799 return DB_INVALID_HANDLE;
03800 }
03801
03802 if ((INT) strlen(pkey->name) + 1 > name_size) {
03803
03804 memcpy(name, pkey->name, name_size - 1);
03805 name[name_size] = 0;
03806 } else
03807 strcpy(name, pkey->name);
03808
03809
03810 if (strcmp(name, "root") == 0)
03811 strcpy(name, "/");
03812
03813 *type = pkey->type;
03814 *num_values = pkey->num_values;
03815 *item_size = pkey->item_size;
03816
03817 if (pkey->type == TID_KEY) {
03818 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
03819 *num_values = pkeylist->num_keys;
03820 }
03821
03822 db_unlock_database(hDB);
03823 }
03824 #endif
03825
03826 return DB_SUCCESS;
03827 }
03828
03829
03830 #ifndef DOXYGEN_SHOULD_SKIP_THIS
03831
03832
03833
03834 INT db_rename_key(HNDLE hDB, HNDLE hKey, char *name)
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854 {
03855 if (rpc_is_remote())
03856 return rpc_call(RPC_DB_RENAME_KEY, hDB, hKey, name);
03857
03858 #ifdef LOCAL_ROUTINES
03859 {
03860 DATABASE_HEADER *pheader;
03861 KEY *pkey;
03862
03863 if (hDB > _database_entries || hDB <= 0) {
03864 cm_msg(MERROR, "db_rename_key", "invalid database handle");
03865 return DB_INVALID_HANDLE;
03866 }
03867
03868 if (!_database[hDB - 1].attached) {
03869 cm_msg(MERROR, "db_rename_key", "invalid database handle");
03870 return DB_INVALID_HANDLE;
03871 }
03872
03873 if (hKey < sizeof(DATABASE_HEADER)) {
03874 cm_msg(MERROR, "db_rename_key", "invalid key handle");
03875 return DB_INVALID_HANDLE;
03876 }
03877
03878 db_lock_database(hDB);
03879
03880 pheader = _database[hDB - 1].database_header;
03881 pkey = (KEY *) ((char *) pheader + hKey);
03882
03883
03884 if (!db_validate_hkey(pheader, hKey)) {
03885 db_unlock_database(hDB);
03886 return DB_INVALID_HANDLE;
03887 }
03888
03889 if (!pkey->type) {
03890 db_unlock_database(hDB);
03891 cm_msg(MERROR, "db_rename_key", "invalid key");
03892 return DB_INVALID_HANDLE;
03893 }
03894
03895 name[NAME_LENGTH] = 0;
03896 strcpy(pkey->name, name);
03897
03898 db_unlock_database(hDB);
03899
03900 }
03901 #endif
03902
03903 return DB_SUCCESS;
03904 }
03905
03906
03907 INT db_reorder_key(HNDLE hDB, HNDLE hKey, INT index)
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930 {
03931 if (rpc_is_remote())
03932 return rpc_call(RPC_DB_REORDER_KEY, hDB, hKey, index);
03933
03934 #ifdef LOCAL_ROUTINES
03935 {
03936 DATABASE_HEADER *pheader;
03937 KEY *pkey, *pprev_key, *pnext_key, *pkey_tmp;
03938 KEYLIST *pkeylist;
03939 INT i;
03940
03941 if (hDB > _database_entries || hDB <= 0) {
03942 cm_msg(MERROR, "db_rename_key", "invalid database handle");
03943 return DB_INVALID_HANDLE;
03944 }
03945
03946 if (!_database[hDB - 1].attached) {
03947 cm_msg(MERROR, "db_rename_key", "invalid database handle");
03948 return DB_INVALID_HANDLE;
03949 }
03950
03951 if (hKey < sizeof(DATABASE_HEADER)) {
03952 cm_msg(MERROR, "db_rename_key", "invalid key handle");
03953 return DB_INVALID_HANDLE;
03954 }
03955
03956 db_lock_database(hDB);
03957
03958 pheader = _database[hDB - 1].database_header;
03959 pkey = (KEY *) ((char *) pheader + hKey);
03960
03961
03962 if (!db_validate_hkey(pheader, hKey)) {
03963 db_unlock_database(hDB);
03964 return DB_INVALID_HANDLE;
03965 }
03966
03967 if (!pkey->type) {
03968 db_unlock_database(hDB);
03969 cm_msg(MERROR, "db_reorder_key", "invalid key");
03970 return DB_INVALID_HANDLE;
03971 }
03972
03973 if (!(pkey->access_mode & MODE_WRITE)) {
03974 db_unlock_database(hDB);
03975 return DB_NO_ACCESS;
03976 }
03977
03978
03979 do {
03980 if (pkey->notify_count) {
03981 db_unlock_database(hDB);
03982 return DB_OPEN_RECORD;
03983 }
03984
03985 if (pkey->parent_keylist == 0)
03986 break;
03987
03988 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
03989 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
03990 } while (TRUE);
03991
03992 pkey = (KEY *) ((char *) pheader + hKey);
03993 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
03994
03995
03996 pnext_key = (KEY *) (PTYPE) pkey->next_key;
03997
03998 if ((KEY *) ((char *) pheader + pkeylist->first_key) == pkey) {
03999
04000 pkeylist->first_key = (PTYPE) pnext_key;
04001 } else {
04002
04003 pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
04004 while ((KEY *) ((char *) pheader + pkey_tmp->next_key) != pkey)
04005 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
04006 pkey_tmp->next_key = (PTYPE) pnext_key;
04007 }
04008
04009
04010 pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
04011 if (index < 0 || index >= pkeylist->num_keys - 1) {
04012
04013
04014
04015 for (i = 0; i < pkeylist->num_keys - 2; i++) {
04016 pprev_key = pkey_tmp;
04017 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
04018 }
04019
04020 pkey_tmp->next_key = (PTYPE) pkey - (PTYPE) pheader;
04021 pkey->next_key = 0;
04022 } else {
04023 if (index == 0) {
04024
04025 pkey->next_key = pkeylist->first_key;
04026 pkeylist->first_key = (PTYPE) pkey - (PTYPE) pheader;
04027 } else {
04028
04029 for (i = 0; i < index - 1; i++)
04030 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
04031
04032 pkey->next_key = pkey_tmp->next_key;
04033 pkey_tmp->next_key = (PTYPE) pkey - (PTYPE) pheader;
04034 }
04035 }
04036
04037 db_unlock_database(hDB);
04038
04039 }
04040 #endif
04041
04042 return DB_SUCCESS;
04043 }
04044
04045
04046 #endif
04047
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073 INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT * buf_size, DWORD type)
04074 {
04075 if (rpc_is_remote())
04076 return rpc_call(RPC_DB_GET_DATA, hDB, hKey, data, buf_size, type);
04077
04078 #ifdef LOCAL_ROUTINES
04079 {
04080 DATABASE_HEADER *pheader;
04081 KEY *pkey;
04082
04083 if (hDB > _database_entries || hDB <= 0) {
04084 cm_msg(MERROR, "db_get_data", "Invalid database handle");
04085 return DB_INVALID_HANDLE;
04086 }
04087
04088 if (!_database[hDB - 1].attached) {
04089 cm_msg(MERROR, "db_get_data", "invalid database handle");
04090 return DB_INVALID_HANDLE;
04091 }
04092
04093 if (hKey < sizeof(DATABASE_HEADER)) {
04094 cm_msg(MERROR, "db_get_data", "invalid key handle");
04095 return DB_INVALID_HANDLE;
04096 }
04097
04098 db_lock_database(hDB);
04099
04100 pheader = _database[hDB - 1].database_header;
04101 pkey = (KEY *) ((char *) pheader + hKey);
04102
04103
04104 if (!db_validate_hkey(pheader, hKey)) {
04105 db_unlock_database(hDB);
04106 return DB_INVALID_HANDLE;
04107 }
04108
04109
04110 if (!(pkey->access_mode & MODE_READ)) {
04111 db_unlock_database(hDB);
04112 return DB_NO_ACCESS;
04113 }
04114
04115 if (!pkey->type) {
04116 db_unlock_database(hDB);
04117 cm_msg(MERROR, "db_get_data", "invalid key");
04118 return DB_INVALID_HANDLE;
04119 }
04120
04121 if (pkey->type != type) {
04122 db_unlock_database(hDB);
04123 cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s",
04124 pkey->name, rpc_tid_name(pkey->type), rpc_tid_name(type));
04125 return DB_TYPE_MISMATCH;
04126 }
04127
04128
04129 if (pkey->type == TID_KEY) {
04130 db_unlock_database(hDB);
04131 cm_msg(MERROR, "db_get_data", "Key cannot contain data");
04132 return DB_TYPE_MISMATCH;
04133 }
04134
04135
04136 if (pkey->data == 0) {
04137 memset(data, 0, *buf_size);
04138 *buf_size = 0;
04139 db_unlock_database(hDB);
04140 return DB_SUCCESS;
04141 }
04142
04143
04144 if (pkey->num_values * pkey->item_size > *buf_size) {
04145 memcpy(data, (char *) pheader + pkey->data, *buf_size);
04146 db_unlock_database(hDB);
04147 cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated", pkey->name);
04148 return DB_TRUNCATED;
04149 }
04150
04151
04152 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
04153 *buf_size = pkey->num_values * pkey->item_size;
04154
04155 db_unlock_database(hDB);
04156
04157 }
04158 #endif
04159
04160 return DB_SUCCESS;
04161 }
04162
04163
04164 #ifndef DOXYGEN_SHOULD_SKIP_THIS
04165
04166
04167 INT db_get_data1(HNDLE hDB, HNDLE hKey, void *data, INT * buf_size,
04168 DWORD type, INT * num_values)
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191
04192
04193 {
04194 if (rpc_is_remote())
04195 return rpc_call(RPC_DB_GET_DATA, hDB, hKey, data, buf_size, type);
04196
04197 #ifdef LOCAL_ROUTINES
04198 {
04199 DATABASE_HEADER *pheader;
04200 KEY *pkey;
04201
04202 if (hDB > _database_entries || hDB <= 0) {
04203 cm_msg(MERROR, "db_get_data", "Invalid database handle");
04204 return DB_INVALID_HANDLE;
04205 }
04206
04207 if (!_database[hDB - 1].attached) {
04208 cm_msg(MERROR, "db_get_data", "invalid database handle");
04209 return DB_INVALID_HANDLE;
04210 }
04211
04212 if (hKey < sizeof(DATABASE_HEADER)) {
04213 cm_msg(MERROR, "db_get_data", "invalid key handle");
04214 return DB_INVALID_HANDLE;
04215 }
04216
04217 db_lock_database(hDB);
04218
04219 pheader = _database[hDB - 1].database_header;
04220 pkey = (KEY *) ((char *) pheader + hKey);
04221
04222
04223 if (!db_validate_hkey(pheader, hKey)) {
04224 db_unlock_database(hDB);
04225 return DB_INVALID_HANDLE;
04226 }
04227
04228
04229 if (!(pkey->access_mode & MODE_READ)) {
04230 db_unlock_database(hDB);
04231 return DB_NO_ACCESS;
04232 }
04233
04234 if (!pkey->type) {
04235 db_unlock_database(hDB);
04236 cm_msg(MERROR, "db_get_data", "invalid key");
04237 return DB_INVALID_HANDLE;
04238 }
04239
04240 if (pkey->type != type) {
04241 db_unlock_database(hDB);
04242 cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s",
04243 pkey->name, rpc_tid_name(pkey->type), rpc_tid_name(type));
04244 return DB_TYPE_MISMATCH;
04245 }
04246
04247
04248 if (pkey->type == TID_KEY) {
04249 db_unlock_database(hDB);
04250 cm_msg(MERROR, "db_get_data", "Key cannot contain data");
04251 return DB_TYPE_MISMATCH;
04252 }
04253
04254
04255 if (pkey->data == 0) {
04256 memset(data, 0, *buf_size);
04257 *buf_size = 0;
04258 db_unlock_database(hDB);
04259 return DB_SUCCESS;
04260 }
04261
04262
04263 if (pkey->num_values * pkey->item_size > *buf_size) {
04264 memcpy(data, (char *) pheader + pkey->data, *buf_size);
04265 db_unlock_database(hDB);
04266 cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated", pkey->name);
04267 return DB_TRUNCATED;
04268 }
04269
04270
04271 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
04272 *buf_size = pkey->num_values * pkey->item_size;
04273 *num_values = pkey->num_values;
04274
04275 db_unlock_database(hDB);
04276
04277 }
04278 #endif
04279
04280 return DB_SUCCESS;
04281 }
04282
04283
04284 #endif
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299 INT db_get_data_index(HNDLE hDB, HNDLE hKey,
04300 void *data, INT * buf_size, INT index, DWORD type)
04301 {
04302 if (rpc_is_remote())
04303 return rpc_call(RPC_DB_GET_DATA_INDEX, hDB, hKey, data, buf_size, index, type);
04304
04305 #ifdef LOCAL_ROUTINES
04306 {
04307 DATABASE_HEADER *pheader;
04308 KEY *pkey;
04309 char str[256];
04310
04311 if (hDB > _database_entries || hDB <= 0) {
04312 cm_msg(MERROR, "db_get_data", "Invalid database handle");
04313 return DB_INVALID_HANDLE;
04314 }
04315
04316 if (!_database[hDB - 1].attached) {
04317 cm_msg(MERROR, "db_get_data", "invalid database handle");
04318 return DB_INVALID_HANDLE;
04319 }
04320
04321 if (hKey < sizeof(DATABASE_HEADER)) {
04322 cm_msg(MERROR, "db_get_data", "invalid key handle");
04323 return DB_INVALID_HANDLE;
04324 }
04325
04326 db_lock_database(hDB);
04327
04328 pheader = _database[hDB - 1].database_header;
04329 pkey = (KEY *) ((char *) pheader + hKey);
04330
04331
04332 if (!db_validate_hkey(pheader, hKey)) {
04333 db_unlock_database(hDB);
04334 return DB_INVALID_HANDLE;
04335 }
04336
04337
04338 if (!(pkey->access_mode & MODE_READ)) {
04339 db_unlock_database(hDB);
04340 return DB_NO_ACCESS;
04341 }
04342
04343 if (!pkey->type) {
04344 db_unlock_database(hDB);
04345 cm_msg(MERROR, "db_get_data_index", "invalid key");
04346 return DB_INVALID_HANDLE;
04347 }
04348
04349 if (pkey->type != type) {
04350 db_unlock_database(hDB);
04351 cm_msg(MERROR, "db_get_data_index",
04352 "\"%s\" is of type %s, not %s", pkey->name,
04353 rpc_tid_name(pkey->type), rpc_tid_name(type));
04354 return DB_TYPE_MISMATCH;
04355 }
04356
04357
04358 if (pkey->type == TID_KEY) {
04359 db_unlock_database(hDB);
04360 cm_msg(MERROR, "db_get_data_index", "Key cannot contain data");
04361 return DB_TYPE_MISMATCH;
04362 }
04363
04364
04365 if (pkey->data == 0) {
04366 memset(data, 0, *buf_size);
04367 *buf_size = 0;
04368 db_unlock_database(hDB);
04369 return DB_SUCCESS;
04370 }
04371
04372
04373 if (index < 0 || index >= pkey->num_values) {
04374 memset(data, 0, *buf_size);
04375 db_unlock_database(hDB);
04376
04377 db_get_path(hDB, hKey, str, sizeof(str));
04378 cm_msg(MERROR, "db_get_data_index",
04379 "index (%d) exceeds array length (%d) for key \"%s\"",
04380 index, pkey->num_values, str);
04381 return DB_OUT_OF_RANGE;
04382 }
04383
04384
04385 if (pkey->item_size > *buf_size) {
04386
04387 memcpy(data, (char *) pheader + pkey->data + index * pkey->item_size, *buf_size);
04388 db_unlock_database(hDB);
04389 cm_msg(MERROR, "db_get_data_index", "data for key \"%s\" truncated", pkey->name);
04390 return DB_TRUNCATED;
04391 }
04392
04393
04394 memcpy(data, (char *) pheader + pkey->data + index * pkey->item_size,
04395 pkey->item_size);
04396 *buf_size = pkey->item_size;
04397
04398 db_unlock_database(hDB);
04399
04400 }
04401 #endif
04402
04403 return DB_SUCCESS;
04404 }
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426 INT db_set_data(HNDLE hDB, HNDLE hKey,
04427 void *data, INT buf_size, INT num_values, DWORD type)
04428 {
04429 if (rpc_is_remote())
04430 return rpc_call(RPC_DB_SET_DATA, hDB, hKey, data, buf_size, num_values, type);
04431
04432 #ifdef LOCAL_ROUTINES
04433 {
04434 DATABASE_HEADER *pheader;
04435 KEY *pkey;
04436
04437 if (hDB > _database_entries || hDB <= 0) {
04438 cm_msg(MERROR, "db_set_data", "invalid database handle");
04439 return DB_INVALID_HANDLE;
04440 }
04441
04442 if (!_database[hDB - 1].attached) {
04443 cm_msg(MERROR, "db_set_data", "invalid database handle");
04444 return DB_INVALID_HANDLE;
04445 }
04446
04447 if (hKey < sizeof(DATABASE_HEADER)) {
04448 cm_msg(MERROR, "db_set_data", "invalid key handle");
04449 return DB_INVALID_HANDLE;
04450 }
04451
04452 if (num_values == 0)
04453 return DB_INVALID_PARAM;
04454
04455 db_lock_database(hDB);
04456
04457 pheader = _database[hDB - 1].database_header;
04458 pkey = (KEY *) ((char *) pheader + hKey);
04459
04460
04461 if (!db_validate_hkey(pheader, hKey)) {
04462 db_unlock_database(hDB);
04463 return DB_INVALID_HANDLE;
04464 }
04465
04466
04467 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
04468 db_unlock_database(hDB);
04469 return DB_NO_ACCESS;
04470 }
04471
04472 if (pkey->type != type) {
04473 db_unlock_database(hDB);
04474 cm_msg(MERROR, "db_set_data", "\"%s\" is of type %s, not %s",
04475 pkey->name, rpc_tid_name(pkey->type), rpc_tid_name(type));
04476 return DB_TYPE_MISMATCH;
04477 }
04478
04479
04480 if (pkey->type == TID_KEY) {
04481 db_unlock_database(hDB);
04482 cm_msg(MERROR, "db_set_data", "Key cannot contain data");
04483 return DB_TYPE_MISMATCH;
04484 }
04485
04486
04487 if (buf_size == 0)
04488 buf_size = pkey->item_size * num_values;
04489
04490
04491 if (pkey->total_size != buf_size) {
04492 pkey->data =
04493 (PTYPE) realloc_data(pheader, (char *) pheader + pkey->data,
04494 pkey->total_size, buf_size);
04495
04496 if (pkey->data == 0) {
04497 db_unlock_database(hDB);
04498 cm_msg(MERROR, "db_set_data", "online database full");
04499 return DB_FULL;
04500 }
04501
04502 pkey->data -= (PTYPE) pheader;
04503 pkey->total_size = buf_size;
04504 }
04505
04506
04507 pkey->num_values = num_values;
04508 if (num_values)
04509 pkey->item_size = buf_size / num_values;
04510
04511
04512 memcpy((char *) pheader + pkey->data, data, buf_size);
04513
04514
04515 pkey->last_written = ss_time();
04516
04517 db_notify_clients(hDB, hKey, TRUE);
04518 db_unlock_database(hDB);
04519
04520 }
04521 #endif
04522
04523 return DB_SUCCESS;
04524 }
04525
04526
04527 #ifndef DOXYGEN_SHOULD_SKIP_THIS
04528
04529
04530 INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542
04543
04544
04545
04546
04547
04548
04549
04550 {
04551 if (rpc_is_remote())
04552 return rpc_call(RPC_DB_SET_NUM_VALUES, hDB, hKey, num_values);
04553
04554 #ifdef LOCAL_ROUTINES
04555 {
04556 DATABASE_HEADER *pheader;
04557 KEY *pkey;
04558 INT new_size;
04559
04560 if (hDB > _database_entries || hDB <= 0) {
04561 cm_msg(MERROR, "db_set_data", "invalid database handle");
04562 return DB_INVALID_HANDLE;
04563 }
04564
04565 if (!_database[hDB - 1].attached) {
04566 cm_msg(MERROR, "db_set_data", "invalid database handle");
04567 return DB_INVALID_HANDLE;
04568 }
04569
04570 if (hKey < sizeof(DATABASE_HEADER)) {
04571 cm_msg(MERROR, "db_set_data", "invalid key handle");
04572 return DB_INVALID_HANDLE;
04573 }
04574
04575 if (num_values == 0)
04576 return DB_INVALID_PARAM;
04577
04578 db_lock_database(hDB);
04579
04580 pheader = _database[hDB - 1].database_header;
04581 pkey = (KEY *) ((char *) pheader + hKey);
04582
04583
04584 if (!db_validate_hkey(pheader, hKey)) {
04585 db_unlock_database(hDB);
04586 return DB_INVALID_HANDLE;
04587 }
04588
04589
04590 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
04591 db_unlock_database(hDB);
04592 return DB_NO_ACCESS;
04593 }
04594
04595
04596 if (pkey->type == TID_KEY) {
04597 db_unlock_database(hDB);
04598 cm_msg(MERROR, "db_set_data", "Key cannot contain data");
04599 return DB_TYPE_MISMATCH;
04600 }
04601
04602
04603 if (pkey->num_values != num_values) {
04604 new_size = pkey->item_size * num_values;
04605 pkey->data =
04606 (PTYPE) realloc_data(pheader, (char *) pheader + pkey->data,
04607 pkey->total_size, new_size);
04608
04609 if (pkey->data == 0) {
04610 db_unlock_database(hDB);
04611 cm_msg(MERROR, "db_set_data", "online database full");
04612 return DB_FULL;
04613 }
04614
04615 pkey->data -= (PTYPE) pheader;
04616 pkey->total_size = new_size;
04617 pkey->num_values = num_values;
04618 }
04619
04620
04621 pkey->last_written = ss_time();
04622
04623 db_notify_clients(hDB, hKey, TRUE);
04624 db_unlock_database(hDB);
04625
04626 }
04627 #endif
04628
04629 return DB_SUCCESS;
04630 }
04631
04632
04633 #endif
04634
04635
04636
04637
04638
04639
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650 INT db_set_data_index(HNDLE hDB, HNDLE hKey,
04651 void *data, INT data_size, INT index, DWORD type)
04652 {
04653 if (rpc_is_remote())
04654 return rpc_call(RPC_DB_SET_DATA_INDEX, hDB, hKey, data, data_size, index, type);
04655
04656 #ifdef LOCAL_ROUTINES
04657 {
04658 DATABASE_HEADER *pheader;
04659 KEY *pkey;
04660
04661 if (hDB > _database_entries || hDB <= 0) {
04662 cm_msg(MERROR, "db_set_data_index", "invalid database handle");
04663 return DB_INVALID_HANDLE;
04664 }
04665
04666 if (!_database[hDB - 1].attached) {
04667 cm_msg(MERROR, "db_set_data_index", "invalid database handle");
04668 return DB_INVALID_HANDLE;
04669 }
04670
04671 if (hKey < sizeof(DATABASE_HEADER)) {
04672 cm_msg(MERROR, "db_set_data_index", "invalid key handle");
04673 return DB_INVALID_HANDLE;
04674 }
04675
04676 db_lock_database(hDB);
04677
04678 pheader = _database[hDB - 1].database_header;
04679 pkey = (KEY *) ((char *) pheader + hKey);
04680
04681
04682 if (!db_validate_hkey(pheader, hKey)) {
04683 db_unlock_database(hDB);
04684 return DB_INVALID_HANDLE;
04685 }
04686
04687
04688 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
04689 db_unlock_database(hDB);
04690 return DB_NO_ACCESS;
04691 }
04692
04693 if (pkey->type != type) {
04694 db_unlock_database(hDB);
04695 cm_msg(MERROR, "db_set_data_index",
04696 "\"%s\" is of type %s, not %s", pkey->name,
04697 rpc_tid_name(pkey->type), rpc_tid_name(type));
04698 return DB_TYPE_MISMATCH;
04699 }
04700
04701
04702 if (pkey->type == TID_KEY) {
04703 db_unlock_database(hDB);
04704 cm_msg(MERROR, "db_set_data_index", "key cannot contain data");
04705 return DB_TYPE_MISMATCH;
04706 }
04707
04708
04709 if (index < 0) {
04710 db_unlock_database(hDB);
04711 cm_msg(MERROR, "db_set_data_index", "invalid index");
04712 return DB_FULL;
04713 }
04714
04715
04716 if (index >= pkey->num_values || pkey->item_size == 0) {
04717 pkey->data =
04718 (PTYPE) realloc_data(pheader, (char *) pheader + pkey->data,
04719 pkey->total_size, data_size * (index + 1));
04720
04721 if (pkey->data == 0) {
04722 db_unlock_database(hDB);
04723 cm_msg(MERROR, "db_set_data_index", "online database full");
04724 return DB_FULL;
04725 }
04726
04727 pkey->data -= (PTYPE) pheader;
04728 if (!pkey->item_size)
04729 pkey->item_size = data_size;
04730 pkey->total_size = data_size * (index + 1);
04731 pkey->num_values = index + 1;
04732 }
04733
04734
04735 if ((type == TID_STRING || type == TID_LINK) &&
04736 (int) strlen((char *) data) + 1 > pkey->item_size)
04737 *((char *) data + pkey->item_size - 1) = 0;
04738
04739
04740 memcpy((char *) pheader + pkey->data + index * pkey->item_size,
04741 data, pkey->item_size);
04742
04743
04744 pkey->last_written = ss_time();
04745
04746 db_notify_clients(hDB, hKey, TRUE);
04747 db_unlock_database(hDB);
04748
04749 }
04750 #endif
04751
04752 return DB_SUCCESS;
04753 }
04754
04755
04756 #ifndef DOXYGEN_SHOULD_SKIP_THIS
04757
04758
04759 INT db_set_data_index2(HNDLE hDB, HNDLE hKey, void *data,
04760 INT data_size, INT index, DWORD type, BOOL bNotify)
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787 {
04788 if (rpc_is_remote())
04789 return rpc_call(RPC_DB_SET_DATA_INDEX2, hDB, hKey,
04790 data, data_size, index, type, bNotify);
04791
04792 #ifdef LOCAL_ROUTINES
04793 {
04794 DATABASE_HEADER *pheader;
04795 KEY *pkey;
04796
04797 if (hDB > _database_entries || hDB <= 0) {
04798 cm_msg(MERROR, "db_set_data_index2", "invalid database handle");
04799 return DB_INVALID_HANDLE;
04800 }
04801
04802 if (!_database[hDB - 1].attached) {
04803 cm_msg(MERROR, "db_set_data_index2", "invalid database handle");
04804 return DB_INVALID_HANDLE;
04805 }
04806
04807 if (hKey < sizeof(DATABASE_HEADER)) {
04808 cm_msg(MERROR, "db_set_data_index2", "invalid key handle");
04809 return DB_INVALID_HANDLE;
04810 }
04811
04812 db_lock_database(hDB);
04813
04814 pheader = _database[hDB - 1].database_header;
04815 pkey = (KEY *) ((char *) pheader + hKey);
04816
04817
04818 if (!db_validate_hkey(pheader, hKey)) {
04819 db_unlock_database(hDB);
04820 return DB_INVALID_HANDLE;
04821 }
04822
04823
04824 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
04825 db_unlock_database(hDB);
04826 return DB_NO_ACCESS;
04827 }
04828
04829 if (pkey->type != type) {
04830 db_unlock_database(hDB);
04831 cm_msg(MERROR, "db_set_data_index2",
04832 "\"%s\" is of type %s, not %s", pkey->name,
04833 rpc_tid_name(pkey->type), rpc_tid_name(type));
04834 return DB_TYPE_MISMATCH;
04835 }
04836
04837
04838 if (pkey->type == TID_KEY) {
04839 db_unlock_database(hDB);
04840 cm_msg(MERROR, "db_set_data_index2", "key cannot contain data");
04841 return DB_TYPE_MISMATCH;
04842 }
04843
04844
04845 if (index < 0) {
04846 db_unlock_database(hDB);
04847 cm_msg(MERROR, "db_set_data_index2", "invalid index");
04848 return DB_FULL;
04849 }
04850
04851
04852 if (index >= pkey->num_values) {
04853 pkey->data =
04854 (PTYPE) realloc_data(pheader, (char *) pheader + pkey->data,
04855 pkey->total_size, data_size * (index + 1));
04856
04857 if (pkey->data == 0) {
04858 db_unlock_database(hDB);
04859 cm_msg(MERROR, "db_set_data_index2", "online database full");
04860 return DB_FULL;
04861 }
04862
04863 pkey->data -= (PTYPE) pheader;
04864 if (!pkey->item_size)
04865 pkey->item_size = data_size;
04866 pkey->total_size = data_size * (index + 1);
04867 pkey->num_values = index + 1;
04868 }
04869
04870
04871 if ((type == TID_STRING || type == TID_LINK) &&
04872 (int) strlen((char *) data) + 1 > pkey->item_size)
04873 *((char *) data + pkey->item_size - 1) = 0;
04874
04875
04876 memcpy((char *) pheader + pkey->data + index * pkey->item_size,
04877 data, pkey->item_size);
04878
04879
04880 pkey->last_written = ss_time();
04881
04882 if (bNotify)
04883 db_notify_clients(hDB, hKey, TRUE);
04884
04885 db_unlock_database(hDB);
04886 }
04887 #endif
04888
04889 return DB_SUCCESS;
04890 }
04891
04892
04893
04894 INT db_merge_data(HNDLE hDB, HNDLE hKeyRoot, char *name, void *data,
04895 INT data_size, INT num_values, INT type)
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920 {
04921 HNDLE hKey;
04922 INT status, old_size;
04923
04924 if (num_values == 0)
04925 return DB_INVALID_PARAM;
04926
04927 status = db_find_key(hDB, hKeyRoot, name, &hKey);
04928 if (status != DB_SUCCESS) {
04929 db_create_key(hDB, hKeyRoot, name, type);
04930 db_find_key(hDB, hKeyRoot, name, &hKey);
04931 status = db_set_data(hDB, hKey, data, data_size, num_values, type);
04932 } else {
04933 old_size = data_size;
04934 db_get_data(hDB, hKey, data, &old_size, type);
04935 status = db_set_data(hDB, hKey, data, data_size, num_values, type);
04936 }
04937
04938 return status;
04939 }
04940
04941
04942 INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966 {
04967 if (rpc_is_remote())
04968 return rpc_call(RPC_DB_SET_MODE, hDB, hKey, mode, recurse);
04969
04970 #ifdef LOCAL_ROUTINES
04971 {
04972 DATABASE_HEADER *pheader;
04973 KEYLIST *pkeylist;
04974 KEY *pkey, *pnext_key;
04975 HNDLE hKeyLink;
04976
04977 if (hDB > _database_entries || hDB <= 0) {
04978 cm_msg(MERROR, "db_set_mode", "invalid database handle");
04979 return DB_INVALID_HANDLE;
04980 }
04981
04982 if (!_database[hDB - 1].attached) {
04983 cm_msg(MERROR, "db_set_mode", "invalid database handle");
04984 return DB_INVALID_HANDLE;
04985 }
04986
04987 if (recurse < 2)
04988 db_lock_database(hDB);
04989
04990 pheader = _database[hDB - 1].database_header;
04991 if (!hKey)
04992 hKey = pheader->root_key;
04993 pkey = (KEY *) ((char *) pheader + hKey);
04994
04995
04996 if (!db_validate_hkey(pheader, hKey)) {
04997 db_unlock_database(hDB);
04998 return DB_INVALID_HANDLE;
04999 }
05000
05001 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
05002
05003 if (pkey->type == TID_KEY && pkeylist->first_key && recurse) {
05004
05005 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
05006
05007 do {
05008 pnext_key = (KEY *) (PTYPE) pkey->next_key;
05009
05010 db_set_mode(hDB, (PTYPE) pkey - (PTYPE) pheader, mode, recurse + 1);
05011
05012 if (pnext_key)
05013 pkey = (KEY *) ((char *) pheader + (PTYPE) pnext_key);
05014 } while (pnext_key);
05015 }
05016
05017 pkey = (KEY *) ((char *) pheader + hKey);
05018
05019
05020 if (pkey->type == TID_LINK) {
05021 db_unlock_database(hDB);
05022 if (*((char *) pheader + pkey->data) == '/')
05023 db_find_key(hDB, 0, (char *) pheader + pkey->data, &hKeyLink);
05024 else
05025 db_find_key(hDB, hKey, (char *) pheader + pkey->data, &hKeyLink);
05026 if (hKeyLink)
05027 db_set_mode(hDB, hKeyLink, mode, recurse > 0);
05028 db_lock_database(hDB);
05029 pheader = _database[hDB - 1].database_header;
05030 pkey = (KEY *) ((char *) pheader + hKey);
05031 }
05032
05033
05034 pkey->access_mode = mode;
05035
05036 if (recurse < 2)
05037 db_unlock_database(hDB);
05038 }
05039 #endif
05040
05041 return DB_SUCCESS;
05042 }
05043
05044
05045 #endif
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061 INT db_load(HNDLE hDB, HNDLE hKeyRoot, char *filename, BOOL bRemote)
05062 {
05063 struct stat stat_buf;
05064 INT hfile, size, n, i, status;
05065 char *buffer;
05066
05067 if (rpc_is_remote() && bRemote)
05068 return rpc_call(RPC_DB_LOAD, hDB, hKeyRoot, filename);
05069
05070
05071 hfile = open(filename, O_RDONLY | O_TEXT, 0644);
05072 if (hfile == -1) {
05073 cm_msg(MERROR, "db_load", "file \"%s\" not found", filename);
05074 return DB_FILE_ERROR;
05075 }
05076
05077
05078 fstat(hfile, &stat_buf);
05079 size = stat_buf.st_size;
05080 buffer = (char *) malloc(size + 1);
05081
05082 if (buffer == NULL) {
05083 cm_msg(MERROR, "db_load", "cannot allocate ODB load buffer");
05084 close(hfile);
05085 return DB_NO_MEMORY;
05086 }
05087
05088 n = 0;
05089
05090 do {
05091 i = read(hfile, buffer + n, size);
05092 if (i <= 0)
05093 break;
05094 n += i;
05095 } while (TRUE);
05096
05097 buffer[n] = 0;
05098
05099 status = db_paste(hDB, hKeyRoot, buffer);
05100
05101 close(hfile);
05102 free(buffer);
05103
05104 return status;
05105 }
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116
05117
05118
05119
05120
05121
05122
05123
05124
05125
05126
05127
05128
05129
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139
05140
05141 INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT * buffer_size, char *path)
05142 {
05143 INT i, j, size, status;
05144 KEY key;
05145 HNDLE hSubkey;
05146 char full_path[MAX_ODB_PATH], str[MAX_STRING_LENGTH * 2];
05147 char *data, line[MAX_STRING_LENGTH * 2];
05148 BOOL bWritten;
05149
05150 strcpy(full_path, path);
05151
05152 bWritten = FALSE;
05153
05154
05155 for (i = 0;; i++) {
05156 db_enum_link(hDB, hKey, i, &hSubkey);
05157
05158 if (i == 0 && !hSubkey) {
05159
05160 db_get_key(hDB, hKey, &key);
05161 size = key.total_size;
05162 data = (char *) malloc(size);
05163 if (data == NULL) {
05164 cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
05165 return DB_NO_MEMORY;
05166 }
05167 line[0] = 0;
05168
05169 if (key.type != TID_KEY) {
05170 db_get_data(hDB, hKey, data, &size, key.type);
05171 if (key.num_values == 1) {
05172 sprintf(line, "%s = %s : ", key.name, tid_name[key.type]);
05173
05174 if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
05175
05176 sprintf(line + strlen(line), "[====#$@$#====]\n");
05177
05178
05179 if ((INT) (strlen(line) + 1) > *buffer_size) {
05180 free(data);
05181 return DB_TRUNCATED;
05182 }
05183
05184 strcpy(buffer, line);
05185 buffer += strlen(line);
05186 *buffer_size -= strlen(line);
05187
05188
05189 if (key.item_size > *buffer_size) {
05190 free(data);
05191 return DB_TRUNCATED;
05192 }
05193
05194 strcpy(buffer, data);
05195 buffer += strlen(data);
05196 *buffer_size -= strlen(data);
05197
05198 strcpy(line, "\n====#$@$#====\n");
05199 } else {
05200 db_sprintf(str, data, key.item_size, 0, key.type);
05201
05202 if (key.type == TID_STRING || key.type == TID_LINK)
05203 sprintf(line + strlen(line), "[%d] ", key.item_size);
05204
05205 sprintf(line + strlen(line), "%s\n", str);
05206 }
05207 } else {
05208 sprintf(line, "%s = %s[%d] :\n", key.name,
05209 tid_name[key.type], key.num_values);
05210
05211 for (j = 0; j < key.num_values; j++) {
05212 if (key.type == TID_STRING || key.type == TID_LINK)
05213 sprintf(line + strlen(line), "[%d] ", key.item_size);
05214 else
05215 sprintf(line + strlen(line), "[%d] ", j);
05216
05217 db_sprintf(str, data, key.item_size, j, key.type);
05218 sprintf(line + strlen(line), "%s\n", str);
05219
05220
05221 if ((INT) (strlen(line) + 1) > *buffer_size) {
05222 free(data);
05223 return DB_TRUNCATED;
05224 }
05225
05226 strcpy(buffer, line);
05227 buffer += strlen(line);
05228 *buffer_size -= strlen(line);
05229 line[0] = 0;
05230 }
05231 }
05232 }
05233
05234
05235 if ((INT) (strlen(line) + 1) > *buffer_size) {
05236 free(data);
05237 return DB_TRUNCATED;
05238 }
05239
05240 strcpy(buffer, line);
05241 buffer += strlen(line);
05242 *buffer_size -= strlen(line);
05243
05244 free(data);
05245 }
05246
05247 if (!hSubkey)
05248 break;
05249
05250 db_get_key(hDB, hSubkey, &key);
05251 size = key.total_size;
05252 data = (char *) malloc(size);
05253 if (data == NULL) {
05254 cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
05255 return DB_NO_MEMORY;
05256 }
05257
05258 line[0] = 0;
05259
05260 if (key.type == TID_KEY) {
05261
05262 if (bWritten) {
05263 if (*buffer_size < 2) {
05264 free(data);
05265 return DB_TRUNCATED;
05266 }
05267
05268 strcpy(buffer, "\n");
05269 buffer += 1;
05270 *buffer_size -= 1;
05271 }
05272
05273 strcpy(str, full_path);
05274 if (str[0] && str[strlen(str) - 1] != '/')
05275 strcat(str, "/");
05276 strcat(str, key.name);
05277
05278
05279 status = db_copy(hDB, hSubkey, buffer, buffer_size, str);
05280 if (status != DB_SUCCESS) {
05281 free(data);
05282 return status;
05283 }
05284
05285 buffer += strlen(buffer);
05286 bWritten = FALSE;
05287 } else {
05288 db_get_data(hDB, hSubkey, data, &size, key.type);
05289 if (!bWritten) {
05290 if (path[0] == 0)
05291 sprintf(line, "[.]\n");
05292 else
05293 sprintf(line, "[%s]\n", path);
05294 bWritten = TRUE;
05295 }
05296
05297 if (key.num_values == 1) {
05298 sprintf(line + strlen(line), "%s = %s : ", key.name, tid_name[key.type]);
05299
05300 if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
05301
05302 sprintf(line + strlen(line), "[====#$@$#====]\n");
05303
05304
05305 data[size - 1] = 0;
05306
05307
05308 if ((INT) (strlen(line) + 1) > *buffer_size) {
05309 free(data);
05310 return DB_TRUNCATED;
05311 }
05312
05313 strcpy(buffer, line);
05314 buffer += strlen(line);
05315 *buffer_size -= strlen(line);
05316
05317
05318 if (key.item_size > *buffer_size) {
05319 free(data);
05320 return DB_TRUNCATED;
05321 }
05322
05323 strcpy(buffer, data);
05324 buffer += strlen(data);
05325 *buffer_size -= strlen(data);
05326
05327 strcpy(line, "\n====#$@$#====\n");
05328 } else {
05329 db_sprintf(str, data, key.item_size, 0, key.type);
05330
05331 if (key.type == TID_STRING || key.type == TID_LINK)
05332 sprintf(line + strlen(line), "[%d] ", key.item_size);
05333
05334 sprintf(line + strlen(line), "%s\n", str);
05335 }
05336 } else {
05337 sprintf(line + strlen(line), "%s = %s[%d] :\n", key.name,
05338 tid_name[key.type], key.num_values);
05339
05340 for (j = 0; j < key.num_values; j++) {
05341 if (key.type == TID_STRING || key.type == TID_LINK)
05342 sprintf(line + strlen(line), "[%d] ", key.item_size);
05343 else
05344 sprintf(line + strlen(line), "[%d] ", j);
05345
05346 db_sprintf(str, data, key.item_size, j, key.type);
05347 sprintf(line + strlen(line), "%s\n", str);
05348
05349
05350 if ((INT) (strlen(line) + 1) > *buffer_size) {
05351 free(data);
05352 return DB_TRUNCATED;
05353 }
05354
05355 strcpy(buffer, line);
05356 buffer += strlen(line);
05357 *buffer_size -= strlen(line);
05358 line[0] = 0;
05359 }
05360 }
05361
05362
05363 if ((INT) (strlen(line) + 1) > *buffer_size) {
05364 free(data);
05365 return DB_TRUNCATED;
05366 }
05367
05368 strcpy(buffer, line);
05369 buffer += strlen(line);
05370 *buffer_size -= strlen(line);
05371 }
05372
05373 free(data);
05374 }
05375
05376 if (bWritten) {
05377 if (*buffer_size < 2)
05378 return DB_TRUNCATED;
05379
05380 strcpy(buffer, "\n");
05381 buffer += 1;
05382 *buffer_size -= 1;
05383 }
05384
05385 return DB_SUCCESS;
05386 }
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396 INT db_paste(HNDLE hDB, HNDLE hKeyRoot, char *buffer)
05397 {
05398 char line[MAX_STRING_LENGTH];
05399 char title[MAX_STRING_LENGTH];
05400 char key_name[MAX_STRING_LENGTH];
05401 char data_str[MAX_STRING_LENGTH + 50];
05402 char test_str[MAX_STRING_LENGTH];
05403 char *pc, *pold, *data;
05404 INT data_size;
05405 INT tid, i, j, n_data, string_length, status, size;
05406 HNDLE hKey;
05407 KEY root_key;
05408 BOOL multi_line;
05409
05410 title[0] = 0;
05411 multi_line = FALSE;
05412
05413 if (hKeyRoot == 0)
05414 db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
05415
05416 db_get_key(hDB, hKeyRoot, &root_key);
05417
05418
05419 data_size = 1000;
05420 data = (char *) malloc(data_size);
05421 if (data == NULL) {
05422 cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
05423 return DB_NO_MEMORY;
05424 }
05425
05426 do {
05427 if (*buffer == 0)
05428 break;
05429
05430 for (i = 0; *buffer != '\n' && *buffer && i < MAX_STRING_LENGTH; i++)
05431 line[i] = *buffer++;
05432
05433 if (i == MAX_STRING_LENGTH) {
05434 cm_msg(MERROR, "db_paste", "line too long");
05435 free(data);
05436 return DB_TRUNCATED;
05437 }
05438
05439 line[i] = 0;
05440 if (*buffer == '\n')
05441 buffer++;
05442
05443
05444 if (line[0] == '[') {
05445
05446 strcpy(title, line + 1);
05447 if (strchr(title, ']'))
05448 *strchr(title, ']') = 0;
05449 if (title[0] && title[strlen(title) - 1] != '/')
05450 strcat(title, "/");
05451 } else {
05452
05453 if (strchr(line, '=') && line[0] != ';') {
05454
05455 pc = strchr(line, '=') + 1;
05456 while (*pc == ' ')
05457 pc++;
05458 strcpy(data_str, pc);
05459
05460
05461 *strchr(line, '=') = 0;
05462
05463 pc = &line[strlen(line) - 1];
05464 while (*pc == ' ')
05465 *pc-- = 0;
05466
05467 key_name[0] = 0;
05468 if (title[0] != '.')
05469 strcpy(key_name, title);
05470
05471 strcat(key_name, line);
05472
05473
05474 strcpy(line, data_str);
05475 if (strchr(line, ' '))
05476 *strchr(line, ' ') = 0;
05477
05478 n_data = 1;
05479 if (strchr(line, '[')) {
05480 n_data = atol(strchr(line, '[') + 1);
05481 *strchr(line, '[') = 0;
05482 }
05483
05484 for (tid = 0; tid < TID_LAST; tid++)
05485 if (strcmp(tid_name[tid], line) == 0)
05486 break;
05487
05488 string_length = 0;
05489
05490 if (tid == TID_LAST)
05491 cm_msg(MERROR, "db_paste",
05492 "found unknown data type \"%s\" in ODB file", line);
05493 else {
05494
05495 pc = data_str;
05496 while (*pc != ' ' && *pc)
05497 pc++;
05498 while ((*pc == ' ' || *pc == ':') && *pc)
05499 pc++;
05500 strcpy(data_str, pc);
05501
05502 if (n_data > 1) {
05503 data_str[0] = 0;
05504 if (!*buffer)
05505 break;
05506
05507 for (j = 0; *buffer != '\n' && *buffer; j++)
05508 data_str[j] = *buffer++;
05509 data_str[j] = 0;
05510 if (*buffer == '\n')
05511 buffer++;
05512 }
05513
05514 for (i = 0; i < n_data; i++) {
05515
05516 pc = &data_str[strlen(data_str) - 1];
05517 while (*pc == '\n' || *pc == '\r')
05518 *pc-- = 0;
05519
05520 if (tid == TID_STRING || tid == TID_LINK) {
05521 if (!string_length) {
05522 if (data_str[1] == '=')
05523 string_length = -1;
05524 else
05525 string_length = atoi(data_str + 1);
05526 if (string_length > MAX_STRING_LENGTH) {
05527 string_length = MAX_STRING_LENGTH;
05528 cm_msg(MERROR, "db_paste",
05529 "found string exceeding MAX_STRING_LENGTH");
05530 }
05531 }
05532
05533 if (string_length == -1) {
05534
05535 if (strstr(buffer, "\n====#$@$#====\n") != NULL) {
05536 string_length =
05537 (PTYPE) strstr(buffer,
05538 "\n====#$@$#====\n") - (PTYPE) buffer + 1;
05539
05540 if (string_length >= data_size) {
05541 data_size += string_length + 100;
05542 data = (char *) realloc(data, data_size);
05543 if (data == NULL) {
05544 cm_msg(MERROR, "db_paste",
05545 "cannot allocate data buffer");
05546 return DB_NO_MEMORY;
05547 }
05548 }
05549
05550 memset(data, 0, data_size);
05551 strncpy(data, buffer, string_length);
05552 data[string_length - 1] = 0;
05553 buffer =
05554 strstr(buffer,
05555 "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
05556 } else
05557 cm_msg(MERROR, "db_paste",
05558 "found multi-line string without termination sequence");
05559 } else {
05560 pc = data_str + 2;
05561 while (*pc && *pc != ' ')
05562 pc++;
05563 while (*pc && *pc == ' ')
05564 pc++;
05565
05566
05567 *(pc + string_length - 1) = 0;
05568
05569
05570 if (string_length * (i + 1) >= data_size) {
05571 data_size += 1000;
05572 data = (char *) realloc(data, data_size);
05573 if (data == NULL) {
05574 cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
05575 return DB_NO_MEMORY;
05576 }
05577 }
05578
05579 strcpy(data + string_length * i, pc);
05580 }
05581 } else {
05582 pc = data_str;
05583
05584 if (n_data > 1 && data_str[0] == '[') {
05585 pc = strchr(data_str, ']') + 1;
05586 while (*pc && *pc == ' ')
05587 pc++;
05588 }
05589
05590 db_sscanf(pc, data, &size, i, tid);
05591
05592
05593 if (size * (i + 1) >= data_size) {
05594 data_size += 1000;
05595 data = (char *) realloc(data, data_size);
05596 if (data == NULL) {
05597 cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
05598 return DB_NO_MEMORY;
05599 }
05600 }
05601
05602 }
05603
05604 if (i < n_data - 1) {
05605 data_str[0] = 0;
05606 if (!*buffer)
05607 break;
05608
05609 pold = buffer;
05610
05611 for (j = 0; *buffer != '\n' && *buffer; j++)
05612 data_str[j] = *buffer++;
05613 data_str[j] = 0;
05614 if (*buffer == '\n')
05615 buffer++;
05616
05617
05618 if (tid != TID_STRING && tid != TID_LINK) {
05619 if (data_str[0] == 0 || (strchr(data_str, '=')
05620 && strchr(data_str, ':')))
05621 buffer = pold;
05622 }
05623 }
05624 }
05625
05626
05627 strcpy(test_str, key_name);
05628 test_str[15] = 0;
05629
05630 if (!equal_ustring(test_str, "/System/Clients")) {
05631 if (root_key.type != TID_KEY) {
05632
05633 hKey = hKeyRoot;
05634 } else {
05635
05636 if (key_name[0] == '/') {
05637 status = db_find_link(hDB, 0, key_name, &hKey);
05638 if (status == DB_NO_KEY) {
05639 db_create_key(hDB, 0, key_name, tid);
05640 status = db_find_link(hDB, 0, key_name, &hKey);
05641 }
05642 } else {
05643 status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
05644 if (status == DB_NO_KEY) {
05645 db_create_key(hDB, hKeyRoot, key_name, tid);
05646 status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
05647 }
05648 }
05649 }
05650
05651
05652 if (hKey) {
05653 if (tid == TID_STRING || tid == TID_LINK)
05654 db_set_data(hDB, hKey, data, string_length * n_data, n_data, tid);
05655 else
05656 db_set_data(hDB, hKey, data,
05657 rpc_tid_size(tid) * n_data, n_data, tid);
05658 }
05659 }
05660 }
05661 }
05662 }
05663 } while (TRUE);
05664
05665 free(data);
05666 return DB_SUCCESS;
05667 }
05668
05669
05670 #ifndef DOXYGEN_SHOULD_SKIP_THIS
05671
05672
05673 void name2c(char *str)
05674
05675
05676
05677
05678
05679
05680
05681 {
05682 if (*str >= '0' && *str <= '9')
05683 *str = '_';
05684
05685 while (*str) {
05686 if (!(*str >= 'a' && *str <= 'z') &&
05687 !(*str >= 'A' && *str <= 'Z') && !(*str >= '0' && *str <= '9'))
05688 *str = '_';
05689 *str = (char) tolower(*str);
05690 str++;
05691 }
05692 }
05693
05694
05695 static void db_save_tree_struct(HNDLE hDB, HNDLE hKey, int hfile, INT level)
05696
05697
05698
05699
05700
05701
05702
05703
05704 {
05705 INT i, index;
05706 KEY key;
05707 HNDLE hSubkey;
05708 char line[MAX_ODB_PATH], str[MAX_STRING_LENGTH];
05709
05710
05711 for (index = 0;; index++) {
05712 db_enum_key(hDB, hKey, index, &hSubkey);
05713
05714 if (!hSubkey)
05715 break;
05716
05717 db_get_key(hDB, hSubkey, &key);
05718
05719 if (key.type != TID_KEY) {
05720 for (i = 0; i <= level; i++)
05721 write(hfile, " ", 2);
05722
05723 switch (key.type) {
05724 case TID_SBYTE:
05725 case TID_CHAR:
05726 strcpy(line, "char");
05727 break;
05728 case TID_SHORT:
05729 strcpy(line, "short");
05730 break;
05731 case TID_FLOAT:
05732 strcpy(line, "float");
05733 break;
05734 case TID_DOUBLE:
05735 strcpy(line, "double");
05736 break;
05737 case TID_BITFIELD:
05738 strcpy(line, "unsigned char");
05739 break;
05740 case TID_STRING:
05741 strcpy(line, "char");
05742 break;
05743 case TID_LINK:
05744 strcpy(line, "char");
05745 break;
05746 default:
05747 strcpy(line, tid_name[key.type]);
05748 break;
05749 }
05750
05751 strcat(line, " ");
05752 strcpy(str, key.name);
05753 name2c(str);
05754
05755 if (key.num_values > 1)
05756 sprintf(str + strlen(str), "[%d]", key.num_values);
05757 if (key.type == TID_STRING || key.type == TID_LINK)
05758 sprintf(str + strlen(str), "[%d]", key.item_size);
05759
05760 strcpy(line + 10, str);
05761 strcat(line, ";\n");
05762
05763 write(hfile, line, strlen(line));
05764 } else {
05765
05766 for (i = 0; i <= level; i++)
05767 write(hfile, " ", 2);
05768
05769 sprintf(line, "struct {\n");
05770 write(hfile, line, strlen(line));
05771 db_save_tree_struct(hDB, hSubkey, hfile, level + 1);
05772
05773 for (i = 0; i <= level; i++)
05774 write(hfile, " ", 2);
05775
05776 strcpy(str, key.name);
05777 name2c(str);
05778
05779 sprintf(line, "} %s;\n", str);
05780 write(hfile, line, strlen(line));
05781 }
05782 }
05783 }
05784
05785
05786 #endif
05787
05788
05789
05790
05791
05792
05793
05794
05795
05796
05797
05798
05799
05800
05801 INT db_save(HNDLE hDB, HNDLE hKey, char *filename, BOOL bRemote)
05802 {
05803 if (rpc_is_remote() && bRemote)
05804 return rpc_call(RPC_DB_SAVE, hDB, hKey, filename, bRemote);
05805
05806 #ifdef LOCAL_ROUTINES
05807 {
05808 INT hfile, size, buffer_size, n, status;
05809 char *buffer, path[256];
05810
05811
05812 hfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, 0644);
05813 if (hfile == -1) {
05814 cm_msg(MERROR, "db_save", "Cannot open file \"%s\"", filename);
05815 return DB_FILE_ERROR;
05816 }
05817
05818 db_get_path(hDB, hKey, path, sizeof(path));
05819
05820 buffer_size = 10000;
05821 do {
05822 buffer = (char *) malloc(buffer_size);
05823 if (buffer == NULL) {
05824 cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
05825 break;
05826 }
05827
05828 size = buffer_size;
05829 status = db_copy(hDB, hKey, buffer, &size, path);
05830 if (status != DB_TRUNCATED) {
05831 n = write(hfile, buffer, buffer_size - size);
05832 free(buffer);
05833
05834 if (n != buffer_size - size) {
05835 cm_msg(MERROR, "db_save", "cannot save .ODB file");
05836 close(hfile);
05837 return DB_FILE_ERROR;
05838 }
05839 break;
05840 }
05841
05842
05843 free(buffer);
05844 buffer_size *= 2;
05845 } while (1);
05846
05847 close(hfile);
05848
05849 }
05850 #endif
05851
05852 return DB_SUCCESS;
05853 }
05854
05855
05856
05857
05858
05859
05860
05861
05862
05863
05864
05865
05866 INT db_save_struct(HNDLE hDB, HNDLE hKey, char *file_name, char *struct_name, BOOL append)
05867 {
05868 KEY key;
05869 char str[100], line[100];
05870 INT status, i, fh;
05871
05872
05873 fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
05874
05875 if (fh == -1) {
05876 cm_msg(MERROR, "db_save_struct", "Cannot open file\"%s\"", file_name);
05877 return DB_FILE_ERROR;
05878 }
05879
05880 status = db_get_key(hDB, hKey, &key);
05881 if (status != DB_SUCCESS) {
05882 cm_msg(MERROR, "db_save_struct", "cannot find key");
05883 return DB_INVALID_HANDLE;
05884 }
05885
05886 sprintf(line, "typedef struct {\n");
05887 write(fh, line, strlen(line));
05888 db_save_tree_struct(hDB, hKey, fh, 0);
05889
05890 if (struct_name && struct_name[0])
05891 strcpy(str, struct_name);
05892 else
05893 strcpy(str, key.name);
05894
05895 name2c(str);
05896 for (i = 0; i < (int) strlen(str); i++)
05897 str[i] = (char) toupper(str[i]);
05898
05899 sprintf(line, "} %s;\n\n", str);
05900 write(fh, line, strlen(line));
05901
05902 close(fh);
05903
05904 return DB_SUCCESS;
05905 }
05906
05907
05908 #ifndef DOXYGEN_SHOULD_SKIP_THIS
05909
05910
05911 INT db_save_string(HNDLE hDB, HNDLE hKey, char *file_name, char *string_name, BOOL append)
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928
05929
05930
05931
05932
05933
05934 {
05935 KEY key;
05936 char str[256], line[256];
05937 INT status, i, size, fh, buffer_size;
05938 char *buffer, *pc;
05939
05940
05941
05942 fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
05943
05944 if (fh == -1) {
05945 cm_msg(MERROR, "db_save_string", "Cannot open file\"%s\"", file_name);
05946 return DB_FILE_ERROR;
05947 }
05948
05949 status = db_get_key(hDB, hKey, &key);
05950 if (status != DB_SUCCESS) {
05951 cm_msg(MERROR, "db_save_string", "cannot find key");
05952 return DB_INVALID_HANDLE;
05953 }
05954
05955 if (string_name && string_name[0])
05956 strcpy(str, string_name);
05957 else
05958 strcpy(str, key.name);
05959
05960 name2c(str);
05961 for (i = 0; i < (int) strlen(str); i++)
05962 str[i] = (char) toupper(str[i]);
05963
05964 sprintf(line, "#define %s(_name) char *_name[] = {\\\n", str);
05965 write(fh, line, strlen(line));
05966
05967 buffer_size = 10000;
05968 do {
05969 buffer = (char *) malloc(buffer_size);
05970 if (buffer == NULL) {
05971 cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
05972 break;
05973 }
05974
05975 size = buffer_size;
05976 status = db_copy(hDB, hKey, buffer, &size, "");
05977 if (status != DB_TRUNCATED)
05978 break;
05979
05980
05981 free(buffer);
05982 buffer_size *= 2;
05983 } while (1);
05984
05985
05986 pc = buffer;
05987
05988 do {
05989 i = 0;
05990 line[i++] = '"';
05991 while (*pc != '\n' && *pc != 0)
05992 line[i++] = *pc++;
05993 strcpy(&line[i], "\",\\\n");
05994 if (i > 0)
05995 write(fh, line, strlen(line));
05996
05997 if (*pc == '\n')
05998 pc++;
05999
06000 } while (*pc);
06001
06002 sprintf(line, "NULL }\n\n");
06003 write(fh, line, strlen(line));
06004
06005 close(fh);
06006 free(buffer);
06007
06008 return DB_SUCCESS;
06009 }
06010
06011
06012 #endif
06013
06014
06015
06016
06017
06018
06019
06020
06021
06022
06023
06024
06025
06026
06027
06028
06029
06030
06031
06032
06033
06034
06035
06036
06037 INT db_sprintf(char *string, void *data, INT data_size, INT index, DWORD type)
06038 {
06039 if (data_size == 0)
06040 sprintf(string, "<NULL>");
06041 else
06042 switch (type) {
06043 case TID_BYTE:
06044 sprintf(string, "%d", *(((BYTE *) data) + index));
06045 break;
06046 case TID_SBYTE:
06047 sprintf(string, "%d", *(((char *) data) + index));
06048 break;
06049 case TID_CHAR:
06050 sprintf(string, "%c", *(((char *) data) + index));
06051 break;
06052 case TID_WORD:
06053 sprintf(string, "%u", *(((WORD *) data) + index));
06054 break;
06055 case TID_SHORT:
06056 sprintf(string, "%d", *(((short *) data) + index));
06057 break;
06058 case TID_DWORD:
06059 sprintf(string, "%lu", *(((DWORD *) data) + index));
06060 break;
06061 case TID_INT:
06062 sprintf(string, "%d", *(((INT *) data) + index));
06063 break;
06064 case TID_BOOL:
06065 sprintf(string, "%c", *(((BOOL *) data) + index) ? 'y' : 'n');
06066 break;
06067 case TID_FLOAT:
06068 sprintf(string, "%g", *(((float *) data) + index));
06069 break;
06070 case TID_DOUBLE:
06071 sprintf(string, "%lg", *(((double *) data) + index));
06072 break;
06073 case TID_BITFIELD:
06074
06075 break;
06076 case TID_STRING:
06077 case TID_LINK:
06078 sprintf(string, "%s", ((char *) data) + data_size * index);
06079 break;
06080 default:
06081 sprintf(string, "<unknown>");
06082 break;
06083 }
06084
06085 return DB_SUCCESS;
06086 }
06087
06088
06089 #ifndef DOXYGEN_SHOULD_SKIP_THIS
06090
06091
06092 INT db_sprintfh(char *string, void *data, INT data_size, INT index, DWORD type)
06093
06094
06095
06096
06097
06098
06099
06100
06101
06102
06103
06104
06105
06106
06107
06108
06109
06110
06111
06112
06113 {
06114 if (data_size == 0)
06115 sprintf(string, "<NULL>");
06116 else
06117 switch (type) {
06118 case TID_BYTE:
06119 sprintf(string, "0x%X", *(((BYTE *) data) + index));
06120 break;
06121 case TID_SBYTE:
06122 sprintf(string, "0x%X", *(((char *) data) + index));
06123 break;
06124 case TID_CHAR:
06125 sprintf(string, "%c", *(((char *) data) + index));
06126 break;
06127 case TID_WORD:
06128 sprintf(string, "0x%X", *(((WORD *) data) + index));
06129 break;
06130 case TID_SHORT:
06131 sprintf(string, "0x%hX", *(((short *) data) + index));
06132 break;
06133 case TID_DWORD:
06134 sprintf(string, "0x%lX", *(((DWORD *) data) + index));
06135 break;
06136 case TID_INT:
06137 sprintf(string, "0x%X", *(((INT *) data) + index));
06138 break;
06139 case TID_BOOL:
06140 sprintf(string, "%c", *(((BOOL *) data) + index) ? 'y' : 'n');
06141 break;
06142 case TID_FLOAT:
06143 sprintf(string, "%g", *(((float *) data) + index));
06144 break;
06145 case TID_DOUBLE:
06146 sprintf(string, "%lg", *(((double *) data) + index));
06147 break;
06148 case TID_BITFIELD:
06149
06150 break;
06151 case TID_STRING:
06152 case TID_LINK:
06153 sprintf(string, "%s", ((char *) data) + data_size * index);
06154 break;
06155 default:
06156 sprintf(string, "<unknown>");
06157 break;
06158 }
06159
06160 return DB_SUCCESS;
06161 }
06162
06163
06164 INT db_sscanf(char *data_str, void *data, INT * data_size, INT i, DWORD tid)
06165
06166
06167
06168
06169
06170
06171
06172
06173
06174
06175
06176
06177
06178
06179
06180
06181
06182
06183
06184 {
06185 DWORD value;
06186 BOOL hex = FALSE;
06187
06188 if (data_str == NULL)
06189 return 0;
06190
06191 *data_size = rpc_tid_size(tid);
06192 if (strncmp(data_str, "0x", 2) == 0) {
06193 hex = TRUE;
06194 sscanf(data_str + 2, "%lx", &value);
06195 }
06196
06197 switch (tid) {
06198 case TID_BYTE:
06199 case TID_SBYTE:
06200 if (hex)
06201 *((char *) data + i) = (char) value;
06202 else
06203 *((char *) data + i) = (char) atoi(data_str);
06204 break;
06205 case TID_CHAR:
06206 *((char *) data + i) = data_str[0];
06207 break;
06208 case TID_WORD:
06209 if (hex)
06210 *((WORD *) data + i) = (WORD) value;
06211 else
06212 *((WORD *) data + i) = (WORD) atoi(data_str);
06213 break;
06214 case TID_SHORT:
06215 if (hex)
06216 *((short int *) data + i) = (short int) value;
06217 else
06218 *((short int *) data + i) = (short int) atoi(data_str);
06219 break;
06220 case TID_DWORD:
06221 if (!hex)
06222 sscanf(data_str, "%lu", &value);
06223
06224 *((DWORD *) data + i) = value;
06225 break;
06226 case TID_INT:
06227 if (hex)
06228 *((INT *) data + i) = value;
06229 else
06230 *((INT *) data + i) = atol(data_str);
06231 break;
06232 case TID_BOOL:
06233 if (data_str[0] == 'y' || data_str[0] == 'Y' || atoi(data_str) > 0)
06234 *((BOOL *) data + i) = 1;
06235 else
06236 *((BOOL *) data + i) = 0;
06237 break;
06238 case TID_FLOAT:
06239 *((float *) data + i) = (float) atof(data_str);
06240 break;
06241 case TID_DOUBLE:
06242 *((double *) data + i) = atof(data_str);
06243 break;
06244 case TID_BITFIELD:
06245
06246 break;
06247 case TID_STRING:
06248 case TID_LINK:
06249 strcpy((char *) data, data_str);
06250 *data_size = strlen(data_str) + 1;
06251 break;
06252 }
06253
06254 return DB_SUCCESS;
06255 }
06256
06257
06258
06259 #ifdef LOCAL_ROUTINES
06260
06261 static void db_recurse_record_tree(HNDLE hDB, HNDLE hKey, void **data,
06262 INT * total_size, INT base_align,
06263 INT * max_align, BOOL bSet, INT convert_flags)
06264
06265
06266
06267
06268
06269
06270
06271
06272 {
06273 DATABASE_HEADER *pheader;
06274 KEYLIST *pkeylist;
06275 KEY *pkey;
06276 INT size, align, corr, total_size_tmp;
06277
06278
06279 pheader = _database[hDB - 1].database_header;
06280 pkey = (KEY *) ((char *) pheader + hKey);
06281
06282 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
06283 if (!pkeylist->first_key)
06284 return;
06285 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
06286
06287
06288 do {
06289 if (pkey->type != TID_KEY) {
06290
06291 align = 1;
06292
06293 if (rpc_tid_size(pkey->type))
06294 align = rpc_tid_size(pkey->type) < base_align ?
06295 rpc_tid_size(pkey->type) : base_align;
06296
06297 if (max_align && align > *max_align)
06298 *max_align = align;
06299
06300 corr = VALIGN(*total_size, align) - *total_size;
06301 *total_size += corr;
06302 if (data)
06303 *data = (void *) ((char *) (*data) + corr);
06304
06305
06306 size = pkey->item_size * pkey->num_values;
06307
06308 if (data) {
06309 if (bSet) {
06310
06311 if (pkey->access_mode & MODE_WRITE) {
06312 memcpy((char *) pheader + pkey->data, *data,
06313 pkey->item_size * pkey->num_values);
06314
06315
06316 if (convert_flags) {
06317 if (pkey->num_values > 1)
06318 rpc_convert_data((char *) pheader + pkey->data,
06319 pkey->type, RPC_FIXARRAY,
06320 pkey->item_size *
06321 pkey->num_values, convert_flags);
06322 else
06323 rpc_convert_single((char *) pheader + pkey->data,
06324 pkey->type, 0, convert_flags);
06325 }
06326
06327
06328 pkey->last_written = ss_time();
06329
06330
06331 if (pkey->notify_count)
06332 db_notify_clients(hDB, (PTYPE) pkey - (PTYPE) pheader, FALSE);
06333 }
06334 } else {
06335
06336 if (pkey->access_mode & MODE_READ) {
06337 memcpy(*data, (char *) pheader + pkey->data, pkey->total_size);
06338
06339
06340 if (convert_flags) {
06341 if (pkey->num_values > 1)
06342 rpc_convert_data(*data, pkey->type,
06343 RPC_FIXARRAY | RPC_OUTGOING,
06344 pkey->item_size *
06345 pkey->num_values, convert_flags);
06346 else
06347 rpc_convert_single(*data, pkey->type, RPC_OUTGOING,
06348 convert_flags);
06349 }
06350 }
06351 }
06352
06353 *data = (char *) (*data) + size;
06354 }
06355
06356 *total_size += size;
06357 } else {
06358
06359
06360 align = 1;
06361
06362 total_size_tmp = *total_size;
06363 db_recurse_record_tree(hDB, (PTYPE) pkey - (PTYPE) pheader,
06364 NULL, &total_size_tmp,
06365 base_align, &align, bSet, convert_flags);
06366
06367 if (max_align && align > *max_align)
06368 *max_align = align;
06369
06370 corr = VALIGN(*total_size, align) - *total_size;
06371 *total_size += corr;
06372 if (data)
06373 *data = (void *) ((char *) (*data) + corr);
06374
06375
06376 db_recurse_record_tree(hDB, (PTYPE) pkey - (PTYPE) pheader,
06377 data, total_size, base_align, NULL, bSet, convert_flags);
06378
06379 corr = VALIGN(*total_size, align) - *total_size;
06380 *total_size += corr;
06381 if (data)
06382 *data = (void *) ((char *) (*data) + corr);
06383
06384 if (bSet && pkey->notify_count)
06385 db_notify_clients(hDB, (PTYPE) pkey - (PTYPE) pheader, FALSE);
06386 }
06387
06388 if (!pkey->next_key)
06389 break;
06390
06391 pkey = (KEY *) ((char *) pheader + pkey->next_key);
06392 } while (TRUE);
06393 }
06394
06395 #endif
06396
06397
06398 #endif
06399
06400
06401
06402
06403
06404
06405
06406
06407
06408
06409
06410
06411
06412
06413 INT db_get_record_size(HNDLE hDB, HNDLE hKey, INT align, INT * buf_size)
06414 {
06415 if (rpc_is_remote()) {
06416 align = ss_get_struct_align();
06417 return rpc_call(RPC_DB_GET_RECORD_SIZE, hDB, hKey, align, buf_size);
06418 }
06419 #ifdef LOCAL_ROUTINES
06420 {
06421 KEY key;
06422 INT status, max_align;
06423
06424 if (!align)
06425 align = ss_get_struct_align();
06426
06427
06428 status = db_get_key(hDB, hKey, &key);
06429 if (status != DB_SUCCESS)
06430 return status;
06431
06432 if (key.type != TID_KEY) {
06433
06434 *buf_size = key.item_size * key.num_values;
06435 return DB_SUCCESS;
06436 }
06437
06438 db_lock_database(hDB);
06439
06440
06441 *buf_size = max_align = 0;
06442 db_recurse_record_tree(hDB, hKey, NULL, buf_size, align, &max_align, 0, 0);
06443
06444
06445 *buf_size = VALIGN(*buf_size, max_align);
06446
06447 db_unlock_database(hDB);
06448 }
06449 #endif
06450
06451 return DB_SUCCESS;
06452 }
06453
06454
06455
06456
06457
06458
06459
06460
06461
06462
06463
06464
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487
06488
06489
06490
06491
06492
06493
06494
06495
06496
06497
06498
06499 INT db_get_record(HNDLE hDB, HNDLE hKey, void *data, INT * buf_size, INT align)
06500 {
06501 if (rpc_is_remote()) {
06502 align = ss_get_struct_align();
06503 return rpc_call(RPC_DB_GET_RECORD, hDB, hKey, data, buf_size, align);
06504 }
06505 #ifdef LOCAL_ROUTINES
06506 {
06507 KEY key;
06508 INT convert_flags, status;
06509 INT total_size;
06510 void *pdata;
06511 char str[256];
06512
06513 convert_flags = 0;
06514
06515 if (!align)
06516 align = ss_get_struct_align();
06517 else
06518
06519 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
06520 convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
06521
06522
06523 status = db_get_key(hDB, hKey, &key);
06524 if (status != DB_SUCCESS)
06525 return status;
06526
06527 if (key.type != TID_KEY) {
06528
06529 if (key.item_size * key.num_values != *buf_size) {
06530 cm_msg(MERROR, "db_get_record", "struct size mismatch for \"%s\"", key.name);
06531 return DB_STRUCT_SIZE_MISMATCH;
06532 }
06533
06534 db_get_data(hDB, hKey, data, buf_size, key.type);
06535
06536 if (convert_flags) {
06537 if (key.num_values > 1)
06538 rpc_convert_data(data, key.type,
06539 RPC_OUTGOING | RPC_FIXARRAY,
06540 key.item_size * key.num_values, convert_flags);
06541 else
06542 rpc_convert_single(data, key.type, RPC_OUTGOING, convert_flags);
06543 }
06544
06545 return DB_SUCCESS;
06546 }
06547
06548
06549 db_get_record_size(hDB, hKey, 0, &total_size);
06550 if (total_size != *buf_size) {
06551 db_get_path(hDB, hKey, str, sizeof(str));
06552 cm_msg(MERROR, "db_get_record",
06553 "struct size mismatch for \"%s\" (%d instead of %d)", str,
06554 *buf_size, total_size);
06555 return DB_STRUCT_SIZE_MISMATCH;
06556 }
06557
06558
06559 pdata = data;
06560 total_size = 0;
06561
06562 db_lock_database(hDB);
06563 db_recurse_record_tree(hDB, hKey, &pdata, &total_size, align,
06564 NULL, FALSE, convert_flags);
06565 db_unlock_database(hDB);
06566
06567 }
06568 #endif
06569
06570 return DB_SUCCESS;
06571 }
06572
06573
06574
06575
06576
06577
06578
06579
06580
06581
06582
06583
06584
06585
06586
06587
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603 INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
06604 {
06605 if (rpc_is_remote()) {
06606 align = ss_get_struct_align();
06607 return rpc_call(RPC_DB_SET_RECORD, hDB, hKey, data, buf_size, align);
06608 }
06609 #ifdef LOCAL_ROUTINES
06610 {
06611 KEY key;
06612 INT convert_flags;
06613 INT total_size;
06614 void *pdata;
06615
06616 convert_flags = 0;
06617
06618 if (!align)
06619 align = ss_get_struct_align();
06620 else
06621
06622 if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
06623 convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
06624
06625
06626 db_get_key(hDB, hKey, &key);
06627 if (key.type != TID_KEY) {
06628
06629 if (key.item_size * key.num_values != buf_size) {
06630 cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
06631 return DB_STRUCT_SIZE_MISMATCH;
06632 }
06633
06634 if (convert_flags) {
06635 if (key.num_values > 1)
06636 rpc_convert_data(data, key.type, RPC_FIXARRAY,
06637 key.item_size * key.num_values, convert_flags);
06638 else
06639 rpc_convert_single(data, key.type, 0, convert_flags);
06640 }
06641
06642 db_set_data(hDB, hKey, data, key.total_size, key.num_values, key.type);
06643 return DB_SUCCESS;
06644 }
06645
06646
06647 db_get_record_size(hDB, hKey, 0, &total_size);
06648 if (total_size != buf_size) {
06649 cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
06650 return DB_STRUCT_SIZE_MISMATCH;
06651 }
06652
06653
06654 pdata = data;
06655 total_size = 0;
06656
06657 db_lock_database(hDB);
06658 db_recurse_record_tree(hDB, hKey, &pdata, &total_size, align,
06659 NULL, TRUE, convert_flags);
06660 db_notify_clients(hDB, hKey, TRUE);
06661 db_unlock_database(hDB);
06662 }
06663 #endif
06664
06665 return DB_SUCCESS;
06666 }
06667
06668
06669 #ifndef DOXYGEN_SHOULD_SKIP_THIS
06670
06671
06672 INT db_add_open_record(HNDLE hDB, HNDLE hKey, WORD access_mode)
06673
06674
06675
06676
06677
06678
06679
06680 {
06681 if (rpc_is_remote())
06682 return rpc_call(RPC_DB_ADD_OPEN_RECORD, hDB, hKey, access_mode);
06683
06684 #ifdef LOCAL_ROUTINES
06685 {
06686 DATABASE_HEADER *pheader;
06687 DATABASE_CLIENT *pclient;
06688 KEY *pkey;
06689 INT i;
06690
06691
06692 db_lock_database(hDB);
06693
06694 pheader = _database[hDB - 1].database_header;
06695 pclient = &pheader->client[_database[hDB - 1].client_index];
06696
06697
06698 for (i = 0; i < pclient->max_index; i++)
06699 if (pclient->open_record[i].handle == hKey)
06700 break;
06701
06702 if (i < pclient->max_index) {
06703 db_unlock_database(hDB);
06704 return DB_SUCCESS;
06705 }
06706
06707
06708 for (i = 0; i < pclient->max_index; i++)
06709 if (pclient->open_record[i].handle == 0)
06710 break;
06711
06712
06713 if (i == MAX_OPEN_RECORDS) {
06714 db_unlock_database(hDB);
06715 return DB_NO_MEMORY;
06716 }
06717
06718 if (i == pclient->max_index)
06719 pclient->max_index++;
06720
06721 pclient->open_record[i].handle = hKey;
06722 pclient->open_record[i].access_mode = access_mode;
06723
06724
06725 pkey = (KEY *) ((char *) pheader + hKey);
06726
06727
06728 if (!db_validate_hkey(pheader, hKey)) {
06729 db_unlock_database(hDB);
06730 return DB_INVALID_HANDLE;
06731 }
06732
06733 pkey->notify_count++;
06734
06735 pclient->num_open_records++;
06736
06737
06738 if (access_mode & MODE_WRITE)
06739 db_set_mode(hDB, hKey, (WORD) (pkey->access_mode | MODE_EXCLUSIVE), 2);
06740
06741 db_unlock_database(hDB);
06742 }
06743 #endif
06744
06745 return DB_SUCCESS;
06746 }
06747
06748
06749 INT db_remove_open_record(HNDLE hDB, HNDLE hKey, BOOL lock)
06750
06751
06752
06753
06754
06755
06756
06757 {
06758 if (rpc_is_remote())
06759 return rpc_call(RPC_DB_REMOVE_OPEN_RECORD, hDB, hKey);
06760
06761 #ifdef LOCAL_ROUTINES
06762 {
06763 DATABASE_HEADER *pheader;
06764 DATABASE_CLIENT *pclient;
06765 KEY *pkey;
06766 INT i, index;
06767
06768 if (lock)
06769 db_lock_database(hDB);
06770
06771 pheader = _database[hDB - 1].database_header;
06772 pclient = &pheader->client[_database[hDB - 1].client_index];
06773
06774
06775 for (index = 0; index < pclient->max_index; index++)
06776 if (pclient->open_record[index].handle == hKey)
06777 break;
06778
06779 if (index == pclient->max_index) {
06780 if (lock)
06781 db_unlock_database(hDB);
06782
06783 return DB_INVALID_HANDLE;
06784 }
06785
06786
06787 pkey = (KEY *) ((char *) pheader + hKey);
06788
06789 if (pkey->notify_count > 0)
06790 pkey->notify_count--;
06791
06792 pclient->num_open_records--;
06793
06794
06795 if (pclient->open_record[index].access_mode & MODE_WRITE)
06796 db_set_mode(hDB, hKey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2);
06797
06798 memset(&pclient->open_record[index], 0, sizeof(OPEN_RECORD));
06799
06800
06801 for (i = pclient->max_index - 1; i >= 0; i--)
06802 if (pclient->open_record[i].handle != 0)
06803 break;
06804 pclient->max_index = i + 1;
06805
06806 if (lock)
06807 db_unlock_database(hDB);
06808 }
06809 #endif
06810
06811 return DB_SUCCESS;
06812 }
06813
06814
06815
06816 #ifdef LOCAL_ROUTINES
06817
06818 INT db_notify_clients(HNDLE hDB, HNDLE hKey, BOOL bWalk)
06819
06820
06821
06822
06823
06824
06825
06826 {
06827 DATABASE_HEADER *pheader;
06828 DATABASE_CLIENT *pclient;
06829 KEY *pkey;
06830 KEYLIST *pkeylist;
06831 INT i, j;
06832 char str[80];
06833
06834 pheader = _database[hDB - 1].database_header;
06835
06836
06837 pkey = (KEY *) ((char *) pheader + hKey);
06838
06839 do {
06840
06841
06842 if (pkey->notify_count)
06843 for (i = 0; i < pheader->max_client_index; i++) {
06844 pclient = &pheader->client[i];
06845 for (j = 0; j < pclient->max_index; j++)
06846 if (pclient->open_record[j].handle == hKey) {
06847
06848 sprintf(str, "O %d %d", hDB, hKey);
06849 ss_resume(pclient->port, str);
06850 }
06851 }
06852
06853 if (pkey->parent_keylist == 0 || !bWalk)
06854 return DB_SUCCESS;
06855
06856 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
06857 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
06858 hKey = (PTYPE) pkey - (PTYPE) pheader;
06859 } while (TRUE);
06860
06861 }
06862
06863 #endif
06864
06865
06866 void merge_records(HNDLE hDB, HNDLE hKey, KEY * pkey, INT level, void *info)
06867 {
06868 char full_name[256], buffer[10000];
06869 INT status, size;
06870 HNDLE hKeyInit;
06871 KEY initkey, key;
06872
06873
06874 db_get_path(hDB, hKey, full_name, 256);
06875 *strchr(full_name, 'O') = 'I';
06876
06877
06878 status = db_find_key(hDB, 0, full_name, &hKeyInit);
06879 if (status == DB_SUCCESS) {
06880 status = db_get_key(hDB, hKeyInit, &initkey);
06881 assert(status == DB_SUCCESS);
06882 status = db_get_key(hDB, hKey, &key);
06883 assert(status == DB_SUCCESS);
06884
06885 if (initkey.type != TID_KEY && initkey.type == key.type) {
06886
06887 size = sizeof(buffer);
06888 status = db_get_data(hDB, hKey, buffer, &size, initkey.type);
06889 assert(status == DB_SUCCESS);
06890 status =
06891 db_set_data(hDB, hKeyInit, buffer, initkey.total_size,
06892 initkey.num_values, initkey.type);
06893 assert(status == DB_SUCCESS);
06894 }
06895 } else if (status == DB_NO_KEY) {
06896
06897 } else {
06898 cm_msg(MERROR, "merge_records",
06899 "aborting on unexpected failure of db_find_key(%s), status %d",
06900 full_name, status);
06901 abort();
06902 }
06903 }
06904
06905 static int open_count;
06906
06907 void check_open_keys(HNDLE hDB, HNDLE hKey, KEY * pkey, INT level, void *info)
06908 {
06909 if (pkey->notify_count)
06910 open_count++;
06911 }
06912
06913
06914 #endif
06915
06916
06917
06918
06919
06920
06921
06922
06923
06924
06925
06926
06927
06928
06929
06930
06931
06932
06933
06934
06935
06936
06937
06938
06939
06940
06941
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951
06952
06953
06954
06955
06956
06957
06958
06959
06960
06961
06962
06963
06964
06965
06966
06967
06968
06969
06970
06971
06972
06973 INT db_create_record(HNDLE hDB, HNDLE hKey, char *orig_key_name, char *init_str)
06974 {
06975 char str[256], key_name[256], *buffer;
06976 INT status, size, i, buffer_size;
06977 HNDLE hKeyTmp, hKeyTmpO, hKeyOrig, hSubkey;
06978
06979 if (rpc_is_remote())
06980 return rpc_call(RPC_DB_CREATE_RECORD, hDB, hKey, orig_key_name, init_str);
06981
06982
06983 db_lock_database(hDB);
06984
06985
06986 strlcpy(key_name, orig_key_name, sizeof(key_name));
06987 if (strlen(key_name) > 1 && key_name[strlen(key_name) - 1] == '/')
06988 key_name[strlen(key_name) - 1] = 0;
06989
06990
06991 status = db_find_key(hDB, hKey, key_name, &hKeyOrig);
06992 if (status == DB_SUCCESS) {
06993 assert(hKeyOrig != 0);
06994
06995 open_count = 0;
06996 db_scan_tree_link(hDB, hKeyOrig, 0, check_open_keys, NULL);
06997 if (open_count) {
06998 db_unlock_database(hDB);
06999 return DB_OPEN_RECORD;
07000 }
07001
07002
07003 sprintf(str, "/System/Tmp/%1dI", ss_gettid());
07004 db_find_key(hDB, 0, str, &hKeyTmp);
07005 if (hKeyTmp)
07006 db_delete_key(hDB, hKeyTmp, FALSE);
07007 db_create_key(hDB, 0, str, TID_KEY);
07008 status = db_find_key(hDB, 0, str, &hKeyTmp);
07009 if (status != DB_SUCCESS) {
07010 db_unlock_database(hDB);
07011 return status;
07012 }
07013
07014 sprintf(str, "/System/Tmp/%1dO", ss_gettid());
07015 db_find_key(hDB, 0, str, &hKeyTmpO);
07016 if (hKeyTmpO)
07017 db_delete_key(hDB, hKeyTmpO, FALSE);
07018 db_create_key(hDB, 0, str, TID_KEY);
07019 status = db_find_key(hDB, 0, str, &hKeyTmpO);
07020 if (status != DB_SUCCESS) {
07021 db_unlock_database(hDB);
07022 return status;
07023 }
07024
07025 status = db_paste(hDB, hKeyTmp, init_str);
07026 if (status != DB_SUCCESS) {
07027 db_unlock_database(hDB);
07028 return status;
07029 }
07030
07031 buffer_size = 10000;
07032 buffer = (char *) malloc(buffer_size);
07033 do {
07034 size = buffer_size;
07035 status = db_copy(hDB, hKeyOrig, buffer, &size, "");
07036 if (status == DB_TRUNCATED) {
07037 buffer_size += 10000;
07038 buffer = (char *) realloc(buffer, buffer_size);
07039 continue;
07040 }
07041 if (status != DB_SUCCESS) {
07042 db_unlock_database(hDB);
07043 return status;
07044 }
07045
07046 } while (status != DB_SUCCESS);
07047
07048 status = db_paste(hDB, hKeyTmpO, buffer);
07049 if (status != DB_SUCCESS) {
07050 free(buffer);
07051 db_unlock_database(hDB);
07052 return status;
07053 }
07054
07055
07056 db_scan_tree_link(hDB, hKeyTmpO, 0, merge_records, NULL);
07057
07058
07059 for (i = 0;; i++) {
07060 db_enum_link(hDB, hKeyOrig, 0, &hSubkey);
07061 if (!hSubkey)
07062 break;
07063
07064 status = db_delete_key(hDB, hSubkey, FALSE);
07065 if (status != DB_SUCCESS) {
07066 free(buffer);
07067 db_unlock_database(hDB);
07068 return status;
07069 }
07070 }
07071
07072
07073 do {
07074 size = buffer_size;
07075 status = db_copy(hDB, hKeyTmp, buffer, &size, "");
07076 if (status == DB_TRUNCATED) {
07077 buffer_size += 10000;
07078 buffer = (char *) realloc(buffer, buffer_size);
07079 continue;
07080 }
07081 if (status != DB_SUCCESS) {
07082 free(buffer);
07083 db_unlock_database(hDB);
07084 return status;
07085 }
07086
07087 } while (status != DB_SUCCESS);
07088
07089 status = db_paste(hDB, hKeyOrig, buffer);
07090 if (status != DB_SUCCESS) {
07091 free(buffer);
07092 db_unlock_database(hDB);
07093 return status;
07094 }
07095
07096
07097 db_delete_key(hDB, hKeyTmp, FALSE);
07098 db_delete_key(hDB, hKeyTmpO, FALSE);
07099
07100 free(buffer);
07101 } else if (status == DB_NO_KEY) {
07102
07103 db_create_key(hDB, hKey, key_name, TID_KEY);
07104 status = db_find_key(hDB, hKey, key_name, &hKeyTmp);
07105 if (status != DB_SUCCESS) {
07106 db_unlock_database(hDB);
07107 return status;
07108 }
07109
07110 status = db_paste(hDB, hKeyTmp, init_str);
07111 if (status != DB_SUCCESS) {
07112 db_unlock_database(hDB);
07113 return status;
07114 }
07115 } else {
07116 cm_msg(MERROR, "db_create_record",
07117 "aborting on unexpected failure of db_find_key(%s), status %d",
07118 key_name, status);
07119 abort();
07120 }
07121
07122 db_unlock_database(hDB);
07123
07124 return DB_SUCCESS;
07125 }
07126
07127
07128
07129
07130
07131
07132
07133
07134
07135
07136
07137
07138
07139
07140
07141
07142
07143 INT db_check_record(HNDLE hDB, HNDLE hKey, char *keyname, char *rec_str, BOOL correct)
07144 {
07145 char line[MAX_STRING_LENGTH];
07146 char title[MAX_STRING_LENGTH];
07147 char key_name[MAX_STRING_LENGTH];
07148 char info_str[MAX_STRING_LENGTH + 50];
07149 char *pc, *pold, *rec_str_orig;
07150 DWORD tid;
07151 INT i, j, n_data, string_length, status;
07152 HNDLE hKeyRoot, hKeyTest;
07153 KEY key;
07154 BOOL multi_line;
07155
07156 if (rpc_is_remote())
07157 return rpc_call(RPC_DB_CHECK_RECORD, hDB, hKey, keyname, rec_str, correct);
07158
07159
07160 status = db_find_key(hDB, hKey, keyname, &hKeyRoot);
07161
07162
07163 if (status == DB_NO_KEY)
07164 return db_create_record(hDB, hKey, keyname, rec_str);
07165
07166 assert(hKeyRoot);
07167
07168 title[0] = 0;
07169 multi_line = FALSE;
07170 rec_str_orig = rec_str;
07171
07172 db_get_key(hDB, hKeyRoot, &key);
07173 if (key.type == TID_KEY)
07174
07175 db_get_next_link(hDB, hKeyRoot, &hKeyTest);
07176 else
07177
07178 hKeyTest = hKeyRoot;
07179
07180 if (hKeyTest == 0 && *rec_str != 0) {
07181 if (correct)
07182 return db_create_record(hDB, hKey, keyname, rec_str_orig);
07183
07184 return DB_STRUCT_MISMATCH;
07185 }
07186
07187 do {
07188 if (*rec_str == 0)
07189 break;
07190
07191 for (i = 0; *rec_str != '\n' && *rec_str && i < MAX_STRING_LENGTH; i++)
07192 line[i] = *rec_str++;
07193
07194 if (i == MAX_STRING_LENGTH) {
07195 cm_msg(MERROR, "db_check_record", "line too long");
07196 return DB_TRUNCATED;
07197 }
07198
07199 line[i] = 0;
07200 if (*rec_str == '\n')
07201 rec_str++;
07202
07203
07204 if (line[0] == '[') {
07205
07206 strcpy(title, line + 1);
07207 if (strchr(title, ']'))
07208 *strchr(title, ']') = 0;
07209 if (title[0] && title[strlen(title) - 1] != '/')
07210 strcat(title, "/");
07211 } else {
07212
07213 if (strchr(line, '=') && line[0] != ';') {
07214
07215 pc = strchr(line, '=') + 1;
07216 while (*pc == ' ')
07217 pc++;
07218 strcpy(info_str, pc);
07219
07220
07221 *strchr(line, '=') = 0;
07222
07223 pc = &line[strlen(line) - 1];
07224 while (*pc == ' ')
07225 *pc-- = 0;
07226
07227 key_name[0] = 0;
07228 if (title[0] != '.')
07229 strcpy(key_name, title);
07230
07231 strcat(key_name, line);
07232
07233
07234 strcpy(line, info_str);
07235 if (strchr(line, ' '))
07236 *strchr(line, ' ') = 0;
07237
07238 n_data = 1;
07239 if (strchr(line, '[')) {
07240 n_data = atol(strchr(line, '[') + 1);
07241 *strchr(line, '[') = 0;
07242 }
07243
07244 for (tid = 0; tid < TID_LAST; tid++)
07245 if (strcmp(tid_name[tid], line) == 0)
07246 break;
07247
07248 string_length = 0;
07249
07250 if (tid == TID_LAST)
07251 cm_msg(MERROR, "db_check_record",
07252 "found unknown data type \"%s\" in ODB file", line);
07253 else {
07254
07255 pc = info_str;
07256 while (*pc != ' ' && *pc)
07257 pc++;
07258 while ((*pc == ' ' || *pc == ':') && *pc)
07259 pc++;
07260
07261 if (n_data > 1) {
07262 info_str[0] = 0;
07263 if (!*rec_str)
07264 break;
07265
07266 for (j = 0; *rec_str != '\n' && *rec_str; j++)
07267 info_str[j] = *rec_str++;
07268 info_str[j] = 0;
07269 if (*rec_str == '\n')
07270 rec_str++;
07271 }
07272
07273 for (i = 0; i < n_data; i++) {
07274
07275 pc = &info_str[strlen(info_str) - 1];
07276 while (*pc == '\n' || *pc == '\r')
07277 *pc-- = 0;
07278
07279 if (tid == TID_STRING || tid == TID_LINK) {
07280 if (!string_length) {
07281 if (info_str[1] == '=')
07282 string_length = -1;
07283 else
07284 string_length = atoi(info_str + 1);
07285 if (string_length > MAX_STRING_LENGTH) {
07286 string_length = MAX_STRING_LENGTH;
07287 cm_msg(MERROR, "db_check_record",
07288 "found string exceeding MAX_STRING_LENGTH");
07289 }
07290 }
07291
07292 if (string_length == -1) {
07293
07294 if (strstr(rec_str, "\n====#$@$#====\n") != NULL) {
07295 string_length =
07296 (PTYPE) strstr(rec_str,
07297 "\n====#$@$#====\n") - (PTYPE) rec_str + 1;
07298
07299 rec_str =
07300 strstr(rec_str,
07301 "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
07302 } else
07303 cm_msg(MERROR, "db_check_record",
07304 "found multi-line string without termination sequence");
07305 } else {
07306 pc = info_str + 2;
07307 while (*pc && *pc != ' ')
07308 pc++;
07309 while (*pc && *pc == ' ')
07310 pc++;
07311
07312
07313 *(pc + string_length - 1) = 0;
07314 }
07315 } else {
07316 pc = info_str;
07317
07318 if (n_data > 1 && info_str[0] == '[') {
07319 pc = strchr(info_str, ']') + 1;
07320 while (*pc && *pc == ' ')
07321 pc++;
07322 }
07323 }
07324
07325 if (i < n_data - 1) {
07326 info_str[0] = 0;
07327 if (!*rec_str)
07328 break;
07329
07330 pold = rec_str;
07331
07332 for (j = 0; *rec_str != '\n' && *rec_str; j++)
07333 info_str[j] = *rec_str++;
07334 info_str[j] = 0;
07335 if (*rec_str == '\n')
07336 rec_str++;
07337
07338
07339 if (tid != TID_STRING && tid != TID_LINK) {
07340 if (info_str[0] == 0 || (strchr(info_str, '=')
07341 && strchr(info_str, ':')))
07342 rec_str = pold;
07343 }
07344 }
07345 }
07346
07347
07348 if (!hKeyTest) {
07349 if (correct)
07350 return db_create_record(hDB, hKey, keyname, rec_str_orig);
07351
07352 return DB_STRUCT_MISMATCH;
07353 }
07354
07355 status = db_get_key(hDB, hKeyTest, &key);
07356 assert(status == DB_SUCCESS);
07357
07358
07359 if (!equal_ustring(key.name, key_name) ||
07360 key.type != tid || key.num_values != n_data) {
07361 if (correct)
07362 return db_create_record(hDB, hKey, keyname, rec_str_orig);
07363
07364 return DB_STRUCT_MISMATCH;
07365 }
07366
07367
07368 db_get_next_link(hDB, hKeyTest, &hKeyTest);
07369 }
07370 }
07371 }
07372 } while (TRUE);
07373
07374 return DB_SUCCESS;
07375 }
07376
07377
07378
07379
07380
07381
07382
07383
07384
07385
07386
07387
07388
07389
07390
07391
07392
07393
07394
07395
07396
07397
07398
07399
07400
07401
07402
07403
07404
07405
07406
07407
07408
07409
07410
07411
07412
07413
07414
07415
07416
07417
07418
07419
07420
07421
07422
07423
07424
07425
07426
07427
07428
07429
07430
07431
07432
07433
07434
07435
07436
07437
07438
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448 INT db_open_record(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size,
07449 WORD access_mode, void (*dispatcher) (INT, INT, void *), void *info)
07450 {
07451 INT index, status, size;
07452 KEY key;
07453 void *data;
07454 char str[256];
07455
07456
07457 if (_record_list_entries == 0) {
07458 _record_list = (RECORD_LIST *) malloc(sizeof(RECORD_LIST));
07459 memset(_record_list, 0, sizeof(RECORD_LIST));
07460 if (_record_list == NULL) {
07461 cm_msg(MERROR, "db_open_record", "not enough memory");
07462 return DB_NO_MEMORY;
07463 }
07464
07465 _record_list_entries = 1;
07466 index = 0;
07467 } else {
07468
07469 for (index = 0; index < _record_list_entries; index++)
07470 if (!_record_list[index].handle)
07471 break;
07472
07473
07474 if (index == _record_list_entries) {
07475 _record_list = (RECORD_LIST *) realloc(_record_list,
07476 sizeof(RECORD_LIST) *
07477 (_record_list_entries + 1));
07478 if (_record_list == NULL) {
07479 cm_msg(MERROR, "db_open_record", "not enough memory");
07480 return DB_NO_MEMORY;
07481 }
07482
07483 memset(&_record_list[_record_list_entries], 0, sizeof(RECORD_LIST));
07484
07485 _record_list_entries++;
07486 }
07487 }
07488
07489 db_get_key(hDB, hKey, &key);
07490
07491
07492 status = db_get_record_size(hDB, hKey, 0, &size);
07493 if (status != DB_SUCCESS) {
07494 _record_list_entries--;
07495 cm_msg(MERROR, "db_open_record", "cannot get record size");
07496 return DB_NO_MEMORY;
07497 }
07498 if (size != rec_size && ptr != NULL) {
07499 _record_list_entries--;
07500 db_get_path(hDB, hKey, str, sizeof(str));
07501 cm_msg(MERROR, "db_open_record",
07502 "struct size mismatch for \"%s\" (%d instead of %d)", str, rec_size, size);
07503 return DB_STRUCT_SIZE_MISMATCH;
07504 }
07505
07506
07507 if (((key.access_mode & MODE_EXCLUSIVE) && (access_mode & MODE_WRITE))
07508 || (!(key.access_mode & MODE_WRITE) && (access_mode & MODE_WRITE))
07509 || (!(key.access_mode & MODE_READ) && (access_mode & MODE_READ))) {
07510 _record_list_entries--;
07511 return DB_NO_ACCESS;
07512 }
07513
07514 if (access_mode & MODE_ALLOC) {
07515 data = malloc(size);
07516 memset(data, 0, size);
07517
07518 if (data == NULL) {
07519 _record_list_entries--;
07520 cm_msg(MERROR, "db_open_record", "not enough memory");
07521 return DB_NO_MEMORY;
07522 }
07523
07524 *((void **) ptr) = data;
07525 } else
07526 data = ptr;
07527
07528
07529 if (access_mode & MODE_READ && data != NULL) {
07530 status = db_get_record(hDB, hKey, data, &size, 0);
07531 if (status != DB_SUCCESS) {
07532 _record_list_entries--;
07533 cm_msg(MERROR, "db_open_record", "cannot get record");
07534 return DB_NO_MEMORY;
07535 }
07536 }
07537
07538
07539 if (access_mode & MODE_WRITE) {
07540
07541 if ((access_mode & MODE_ALLOC) == 0) {
07542 status = db_set_record(hDB, hKey, data, size, 0);
07543 if (status != DB_SUCCESS) {
07544 _record_list_entries--;
07545 cm_msg(MERROR, "db_open_record", "cannot set record");
07546 return DB_NO_MEMORY;
07547 }
07548 }
07549
07550
07551 _record_list[index].copy = malloc(size);
07552 if (_record_list[index].copy == NULL) {
07553 cm_msg(MERROR, "db_open_record", "not enough memory");
07554 return DB_NO_MEMORY;
07555 }
07556
07557 memcpy(_record_list[index].copy, data, size);
07558 }
07559
07560
07561 _record_list[index].handle = hKey;
07562 _record_list[index].hDB = hDB;
07563 _record_list[index].access_mode = access_mode;
07564 _record_list[index].data = data;
07565 _record_list[index].buf_size = size;
07566 _record_list[index].dispatcher = dispatcher;
07567 _record_list[index].info = info;
07568
07569
07570 db_add_open_record(hDB, hKey, (WORD) (access_mode & ~MODE_ALLOC));
07571
07572 return DB_SUCCESS;
07573 }
07574
07575
07576
07577
07578
07579
07580
07581
07582 INT db_close_record(HNDLE hDB, HNDLE hKey)
07583 {
07584 #ifdef LOCAL_ROUTINES
07585 {
07586 INT i;
07587
07588 for (i = 0; i < _record_list_entries; i++)
07589 if (_record_list[i].handle == hKey && _record_list[i].hDB == hDB)
07590 break;
07591
07592 if (i == _record_list_entries)
07593 return DB_INVALID_HANDLE;
07594
07595
07596 db_remove_open_record(hDB, hKey, TRUE);
07597
07598
07599 if (_record_list[i].access_mode & MODE_ALLOC)
07600 free(_record_list[i].data);
07601
07602 if (_record_list[i].access_mode & MODE_WRITE)
07603 free(_record_list[i].copy);
07604
07605 memset(&_record_list[i], 0, sizeof(RECORD_LIST));
07606 }
07607 #endif
07608
07609 return DB_SUCCESS;
07610 }
07611
07612
07613
07614
07615
07616
07617
07618
07619 INT db_close_all_records()
07620 {
07621 INT i;
07622
07623 for (i = 0; i < _record_list_entries; i++) {
07624 if (_record_list[i].handle) {
07625 if (_record_list[i].access_mode & MODE_WRITE)
07626 free(_record_list[i].copy);
07627
07628 if (_record_list[i].access_mode & MODE_ALLOC)
07629 free(_record_list[i].data);
07630
07631 memset(&_record_list[i], 0, sizeof(RECORD_LIST));
07632 }
07633 }
07634
07635 if (_record_list_entries > 0) {
07636 _record_list_entries = 0;
07637 free(_record_list);
07638 }
07639
07640 return DB_SUCCESS;
07641 }
07642
07643
07644
07645
07646
07647
07648
07649
07650
07651
07652
07653
07654 INT db_update_record(INT hDB, INT hKey, int socket)
07655 {
07656 INT i, size, convert_flags, status;
07657 char buffer[32];
07658 NET_COMMAND *nc;
07659
07660
07661 if (socket) {
07662 convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
07663
07664 if (convert_flags & CF_ASCII) {
07665 sprintf(buffer, "MSG_ODB&%d&%d", hDB, hKey);
07666 send_tcp(socket, buffer, strlen(buffer) + 1, 0);
07667 } else {
07668 nc = (NET_COMMAND *) buffer;
07669
07670 nc->header.routine_id = MSG_ODB;
07671 nc->header.param_size = 2 * sizeof(INT);
07672 *((INT *) nc->param) = hDB;
07673 *((INT *) nc->param + 1) = hKey;
07674
07675 if (convert_flags) {
07676 rpc_convert_single(&nc->header.routine_id, TID_DWORD,
07677 RPC_OUTGOING, convert_flags);
07678 rpc_convert_single(&nc->header.param_size, TID_DWORD,
07679 RPC_OUTGOING, convert_flags);
07680 rpc_convert_single(&nc->param[0], TID_DWORD, RPC_OUTGOING, convert_flags);
07681 rpc_convert_single(&nc->param[4], TID_DWORD, RPC_OUTGOING, convert_flags);
07682 }
07683
07684
07685 send_tcp(socket, buffer, sizeof(NET_COMMAND_HEADER) + 2 * sizeof(INT), 0);
07686 }
07687
07688 return DB_SUCCESS;
07689 }
07690
07691 status = DB_INVALID_HANDLE;
07692
07693
07694 for (i = 0; i < _record_list_entries; i++)
07695 if (_record_list[i].handle == hKey) {
07696 status = DB_SUCCESS;
07697
07698
07699 if ((_record_list[i].access_mode & MODE_WRITE) == 0) {
07700 size = _record_list[i].buf_size;
07701 if (_record_list[i].data != NULL)
07702 db_get_record(hDB, hKey, _record_list[i].data, &size, 0);
07703
07704
07705 if (_record_list[i].dispatcher)
07706 _record_list[i].dispatcher(hDB, hKey, _record_list[i].info);
07707 }
07708 }
07709
07710 return DB_SUCCESS;
07711 }
07712
07713
07714
07715
07716
07717
07718
07719
07720
07721
07722
07723
07724
07725
07726
07727
07728
07729
07730
07731
07732
07733
07734
07735
07736
07737
07738
07739
07740
07741
07742
07743
07744
07745
07746
07747
07748
07749
07750
07751
07752
07753
07754
07755
07756
07757
07758
07759
07760
07761
07762
07763
07764
07765
07766
07767
07768
07769
07770
07771
07772
07773
07774
07775
07776
07777
07778
07779
07780
07781
07782
07783
07784
07785
07786
07787
07788
07789
07790
07791
07792
07793
07794
07795
07796
07797
07798
07799
07800
07801
07802
07803
07804
07805
07806
07807
07808
07809
07810
07811
07812
07813
07814
07815
07816
07817
07818
07819
07820
07821
07822
07823
07824
07825
07826
07827
07828
07829
07830
07831
07832
07833
07834
07835
07836
07837
07838
07839
07840
07841
07842
07843
07844
07845
07846
07847
07848
07849
07850
07851
07852
07853
07854
07855
07856
07857
07858
07859
07860
07861
07862 INT db_send_changed_records()
07863 {
07864 INT i;
07865
07866 for (i = 0; i < _record_list_entries; i++)
07867 if (_record_list[i].access_mode & MODE_WRITE) {
07868 if (memcmp
07869 (_record_list[i].copy, _record_list[i].data,
07870 _record_list[i].buf_size) != 0) {
07871
07872 if (rpc_is_remote())
07873 rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
07874 db_set_record(_record_list[i].hDB,
07875 _record_list[i].handle,
07876 _record_list[i].data, _record_list[i].buf_size, 0);
07877 if (rpc_is_remote())
07878 rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
07879 memcpy(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size);
07880 }
07881 }
07882
07883 return DB_SUCCESS;
07884 }
07885
07886
07887
07888
07889
07890
07891
07892