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