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