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