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