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