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