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