1 /* ccapi/lib/ccapi_ccache.c */ 2 /* 3 * Copyright 2006, 2007 Massachusetts Institute of Technology. 4 * All Rights Reserved. 5 * 6 * Export of this software from the United States of America may 7 * require a specific license from the United States Government. 8 * It is the responsibility of any person or organization contemplating 9 * export to obtain such a license before exporting. 10 * 11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 12 * distribute this software and its documentation for any purpose and 13 * without fee is hereby granted, provided that the above copyright 14 * notice appear in all copies and that both that copyright notice and 15 * this permission notice appear in supporting documentation, and that 16 * the name of M.I.T. not be used in advertising or publicity pertaining 17 * to distribution of the software without specific, written prior 18 * permission. Furthermore if you modify this software you must label 19 * your software as modified software and not distribute it in such a 20 * fashion that it might be confused with the original M.I.T. software. 21 * M.I.T. makes no representations about the suitability of 22 * this software for any purpose. It is provided "as is" without express 23 * or implied warranty. 24 */ 25 26 #include "ccapi_ccache.h" 27 28 #include "ccapi_string.h" 29 #include "ccapi_credentials.h" 30 #include "ccapi_credentials_iterator.h" 31 #include "ccapi_ipc.h" 32 33 /* ------------------------------------------------------------------------ */ 34 35 typedef struct cci_ccache_d { 36 cc_ccache_f *functions; 37 #if TARGET_OS_MAC 38 cc_ccache_f *vector_functions; 39 #endif 40 cci_identifier_t identifier; 41 cc_time_t last_wait_for_change_time; 42 cc_uint32 compat_version; 43 } *cci_ccache_t; 44 45 /* ------------------------------------------------------------------------ */ 46 47 struct cci_ccache_d cci_ccache_initializer = { 48 NULL 49 VECTOR_FUNCTIONS_INITIALIZER, 50 NULL, 51 0 52 }; 53 54 cc_ccache_f cci_ccache_f_initializer = { 55 ccapi_ccache_release, 56 ccapi_ccache_destroy, 57 ccapi_ccache_set_default, 58 ccapi_ccache_get_credentials_version, 59 ccapi_ccache_get_name, 60 ccapi_ccache_get_principal, 61 ccapi_ccache_set_principal, 62 ccapi_ccache_store_credentials, 63 ccapi_ccache_remove_credentials, 64 ccapi_ccache_new_credentials_iterator, 65 ccapi_ccache_move, 66 ccapi_ccache_lock, 67 ccapi_ccache_unlock, 68 ccapi_ccache_get_last_default_time, 69 ccapi_ccache_get_change_time, 70 ccapi_ccache_compare, 71 ccapi_ccache_get_kdc_time_offset, 72 ccapi_ccache_set_kdc_time_offset, 73 ccapi_ccache_clear_kdc_time_offset, 74 ccapi_ccache_wait_for_change 75 }; 76 77 /* ------------------------------------------------------------------------ */ 78 79 cc_int32 cci_ccache_new (cc_ccache_t *out_ccache, 80 cci_identifier_t in_identifier) 81 { 82 cc_int32 err = ccNoError; 83 cci_ccache_t ccache = NULL; 84 85 if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } 86 if (!in_identifier) { err = cci_check_error (ccErrBadParam); } 87 88 if (!err) { 89 ccache = malloc (sizeof (*ccache)); 90 if (ccache) { 91 *ccache = cci_ccache_initializer; 92 } else { 93 err = cci_check_error (ccErrNoMem); 94 } 95 } 96 97 if (!err) { 98 ccache->functions = malloc (sizeof (*ccache->functions)); 99 if (ccache->functions) { 100 *ccache->functions = cci_ccache_f_initializer; 101 } else { 102 err = cci_check_error (ccErrNoMem); 103 } 104 } 105 106 if (!err) { 107 err = cci_identifier_copy (&ccache->identifier, in_identifier); 108 } 109 110 if (!err) { 111 *out_ccache = (cc_ccache_t) ccache; 112 ccache = NULL; /* take ownership */ 113 } 114 115 ccapi_ccache_release ((cc_ccache_t) ccache); 116 117 return cci_check_error (err); 118 } 119 120 /* ------------------------------------------------------------------------ */ 121 122 cc_int32 cci_ccache_write (cc_ccache_t in_ccache, 123 k5_ipc_stream in_stream) 124 { 125 cc_int32 err = ccNoError; 126 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 127 128 if (!in_ccache) { err = cci_check_error (ccErrBadParam); } 129 if (!in_stream) { err = cci_check_error (ccErrBadParam); } 130 131 if (!err) { 132 err = cci_identifier_write (ccache->identifier, in_stream); 133 } 134 135 return cci_check_error (err); 136 } 137 138 #ifdef TARGET_OS_MAC 139 #pragma mark - 140 #endif 141 142 /* ------------------------------------------------------------------------ */ 143 144 cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache) 145 { 146 cc_int32 err = ccNoError; 147 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 148 149 if (!io_ccache) { err = ccErrBadParam; } 150 151 if (!err) { 152 cci_identifier_release (ccache->identifier); 153 154 free ((char *) ccache->functions); 155 free (ccache); 156 } 157 158 return err; 159 } 160 161 /* ------------------------------------------------------------------------ */ 162 163 cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache) 164 { 165 cc_int32 err = ccNoError; 166 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 167 168 if (!io_ccache) { err = cci_check_error (ccErrBadParam); } 169 170 if (!err) { 171 err = cci_ipc_send (cci_ccache_destroy_msg_id, 172 ccache->identifier, 173 NULL, 174 NULL); 175 } 176 177 if (!err) { 178 err = ccapi_ccache_release (io_ccache); 179 } 180 181 return cci_check_error (err); 182 } 183 184 /* ------------------------------------------------------------------------ */ 185 186 cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache) 187 { 188 cc_int32 err = ccNoError; 189 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 190 191 if (!io_ccache) { err = cci_check_error (ccErrBadParam); } 192 193 if (!err) { 194 err = cci_ipc_send (cci_ccache_set_default_msg_id, 195 ccache->identifier, 196 NULL, 197 NULL); 198 } 199 200 return cci_check_error (err); 201 } 202 203 /* ------------------------------------------------------------------------ */ 204 205 cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t in_ccache, 206 cc_uint32 *out_credentials_version) 207 { 208 cc_int32 err = ccNoError; 209 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 210 k5_ipc_stream reply = NULL; 211 212 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 213 if (!out_credentials_version) { err = cci_check_error (ccErrBadParam); } 214 215 if (!err) { 216 err = cci_ipc_send (cci_ccache_get_credentials_version_msg_id, 217 ccache->identifier, 218 NULL, 219 &reply); 220 } 221 222 if (!err) { 223 err = krb5int_ipc_stream_read_uint32 (reply, out_credentials_version); 224 } 225 226 krb5int_ipc_stream_release (reply); 227 228 return cci_check_error (err); 229 } 230 231 /* ------------------------------------------------------------------------ */ 232 233 cc_int32 ccapi_ccache_get_name (cc_ccache_t in_ccache, 234 cc_string_t *out_name) 235 { 236 cc_int32 err = ccNoError; 237 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 238 k5_ipc_stream reply = NULL; 239 char *name = NULL; 240 241 if (!in_ccache) { err = cci_check_error (ccErrBadParam); } 242 if (!out_name ) { err = cci_check_error (ccErrBadParam); } 243 244 if (!err) { 245 err = cci_ipc_send (cci_ccache_get_name_msg_id, 246 ccache->identifier, 247 NULL, 248 &reply); 249 } 250 251 if (!err) { 252 err = krb5int_ipc_stream_read_string (reply, &name); 253 } 254 255 if (!err) { 256 err = cci_string_new (out_name, name); 257 } 258 259 krb5int_ipc_stream_release (reply); 260 krb5int_ipc_stream_free_string (name); 261 262 return cci_check_error (err); 263 } 264 265 /* ------------------------------------------------------------------------ */ 266 267 cc_int32 ccapi_ccache_get_principal (cc_ccache_t in_ccache, 268 cc_uint32 in_credentials_version, 269 cc_string_t *out_principal) 270 { 271 cc_int32 err = ccNoError; 272 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 273 k5_ipc_stream request = NULL; 274 k5_ipc_stream reply = NULL; 275 char *principal = NULL; 276 277 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 278 if (!out_principal) { err = cci_check_error (ccErrBadParam); } 279 280 if (!err) { 281 err = krb5int_ipc_stream_new (&request); 282 } 283 284 if (!err) { 285 err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); 286 } 287 288 if (!err) { 289 err = cci_ipc_send (cci_ccache_get_principal_msg_id, 290 ccache->identifier, 291 request, 292 &reply); 293 } 294 295 if (!err) { 296 err = krb5int_ipc_stream_read_string (reply, &principal); 297 } 298 299 if (!err) { 300 err = cci_string_new (out_principal, principal); 301 } 302 303 krb5int_ipc_stream_release (request); 304 krb5int_ipc_stream_release (reply); 305 krb5int_ipc_stream_free_string (principal); 306 307 return cci_check_error (err); 308 } 309 310 /* ------------------------------------------------------------------------ */ 311 312 cc_int32 ccapi_ccache_set_principal (cc_ccache_t io_ccache, 313 cc_uint32 in_credentials_version, 314 const char *in_principal) 315 { 316 cc_int32 err = ccNoError; 317 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 318 k5_ipc_stream request = NULL; 319 320 if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } 321 if (!in_principal) { err = cci_check_error (ccErrBadParam); } 322 323 if (!err) { 324 err = krb5int_ipc_stream_new (&request); 325 } 326 327 if (!err) { 328 err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); 329 } 330 331 if (!err) { 332 err = krb5int_ipc_stream_write_string (request, in_principal); 333 } 334 335 if (!err) { 336 err = cci_ipc_send (cci_ccache_set_principal_msg_id, 337 ccache->identifier, 338 request, 339 NULL); 340 } 341 342 krb5int_ipc_stream_release (request); 343 344 return cci_check_error (err); 345 } 346 347 /* ------------------------------------------------------------------------ */ 348 349 cc_int32 ccapi_ccache_store_credentials (cc_ccache_t io_ccache, 350 const cc_credentials_union *in_credentials_union) 351 { 352 cc_int32 err = ccNoError; 353 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 354 k5_ipc_stream request = NULL; 355 356 if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } 357 if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } 358 359 if (!err) { 360 err = krb5int_ipc_stream_new (&request); 361 } 362 363 if (!err) { 364 err = cci_credentials_union_write (in_credentials_union, request); 365 } 366 367 if (!err) { 368 err = cci_ipc_send (cci_ccache_store_credentials_msg_id, 369 ccache->identifier, 370 request, 371 NULL); 372 } 373 374 krb5int_ipc_stream_release (request); 375 376 return cci_check_error (err); 377 } 378 379 /* ------------------------------------------------------------------------ */ 380 381 cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t io_ccache, 382 cc_credentials_t in_credentials) 383 { 384 cc_int32 err = ccNoError; 385 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 386 k5_ipc_stream request = NULL; 387 388 if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } 389 if (!in_credentials) { err = cci_check_error (ccErrBadParam); } 390 391 if (!err) { 392 err = krb5int_ipc_stream_new (&request); 393 } 394 395 if (!err) { 396 err = cci_credentials_write (in_credentials, request); 397 } 398 399 if (!err) { 400 err = cci_ipc_send (cci_ccache_remove_credentials_msg_id, 401 ccache->identifier, 402 request, 403 NULL); 404 } 405 406 krb5int_ipc_stream_release (request); 407 408 return cci_check_error (err); 409 } 410 411 /* ------------------------------------------------------------------------ */ 412 413 cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t in_ccache, 414 cc_credentials_iterator_t *out_credentials_iterator) 415 { 416 cc_int32 err = ccNoError; 417 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 418 k5_ipc_stream reply = NULL; 419 cci_identifier_t identifier = NULL; 420 421 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 422 if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } 423 424 if (!err) { 425 err = cci_ipc_send (cci_ccache_new_credentials_iterator_msg_id, 426 ccache->identifier, 427 NULL, 428 &reply); 429 } 430 431 if (!err) { 432 err = cci_identifier_read (&identifier, reply); 433 } 434 435 if (!err) { 436 err = cci_credentials_iterator_new (out_credentials_iterator, identifier); 437 } 438 439 krb5int_ipc_stream_release (reply); 440 cci_identifier_release (identifier); 441 442 return cci_check_error (err); 443 } 444 445 /* ------------------------------------------------------------------------ */ 446 /* Note: message is sent as the destination to avoid extra work on the */ 447 /* server when deleting it the source ccache. */ 448 449 cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache, 450 cc_ccache_t io_destination_ccache) 451 { 452 cc_int32 err = ccNoError; 453 cci_ccache_t source_ccache = (cci_ccache_t) io_source_ccache; 454 cci_ccache_t destination_ccache = (cci_ccache_t) io_destination_ccache; 455 k5_ipc_stream request = NULL; 456 457 if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); } 458 if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } 459 460 if (!err) { 461 err = krb5int_ipc_stream_new (&request); 462 } 463 464 if (!err) { 465 err = cci_identifier_write (source_ccache->identifier, request); 466 } 467 468 if (!err) { 469 err = cci_ipc_send (cci_ccache_move_msg_id, 470 destination_ccache->identifier, 471 request, 472 NULL); 473 } 474 475 krb5int_ipc_stream_release (request); 476 477 return cci_check_error (err); 478 } 479 480 /* ------------------------------------------------------------------------ */ 481 482 cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache, 483 cc_uint32 in_lock_type, 484 cc_uint32 in_block) 485 { 486 cc_int32 err = ccNoError; 487 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 488 k5_ipc_stream request = NULL; 489 490 if (!io_ccache) { err = cci_check_error (ccErrBadParam); } 491 492 if (!err) { 493 err = krb5int_ipc_stream_new (&request); 494 } 495 496 if (!err) { 497 err = krb5int_ipc_stream_write_uint32 (request, in_lock_type); 498 } 499 500 if (!err) { 501 err = krb5int_ipc_stream_write_uint32 (request, in_block); 502 } 503 504 if (!err) { 505 err = cci_ipc_send (cci_ccache_lock_msg_id, 506 ccache->identifier, 507 request, 508 NULL); 509 } 510 511 krb5int_ipc_stream_release (request); 512 513 return cci_check_error (err); 514 } 515 516 /* ------------------------------------------------------------------------ */ 517 518 cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache) 519 { 520 cc_int32 err = ccNoError; 521 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 522 523 if (!io_ccache) { err = cci_check_error (ccErrBadParam); } 524 525 if (!err) { 526 err = cci_ipc_send (cci_ccache_unlock_msg_id, 527 ccache->identifier, 528 NULL, 529 NULL); 530 } 531 532 return cci_check_error (err); 533 } 534 535 /* ------------------------------------------------------------------------ */ 536 537 cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t in_ccache, 538 cc_time_t *out_last_default_time) 539 { 540 cc_int32 err = ccNoError; 541 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 542 k5_ipc_stream reply = NULL; 543 544 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 545 if (!out_last_default_time) { err = cci_check_error (ccErrBadParam); } 546 547 if (!err) { 548 err = cci_ipc_send (cci_ccache_get_last_default_time_msg_id, 549 ccache->identifier, 550 NULL, 551 &reply); 552 } 553 554 if (!err) { 555 err = krb5int_ipc_stream_read_time (reply, out_last_default_time); 556 } 557 558 krb5int_ipc_stream_release (reply); 559 560 return cci_check_error (err); 561 } 562 563 /* ------------------------------------------------------------------------ */ 564 565 cc_int32 ccapi_ccache_get_change_time (cc_ccache_t in_ccache, 566 cc_time_t *out_change_time) 567 { 568 cc_int32 err = ccNoError; 569 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 570 k5_ipc_stream reply = NULL; 571 572 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 573 if (!out_change_time) { err = cci_check_error (ccErrBadParam); } 574 575 if (!err) { 576 err = cci_ipc_send (cci_ccache_get_change_time_msg_id, 577 ccache->identifier, 578 NULL, 579 &reply); 580 } 581 582 if (!err) { 583 err = krb5int_ipc_stream_read_time (reply, out_change_time); 584 } 585 586 krb5int_ipc_stream_release (reply); 587 588 return cci_check_error (err); 589 } 590 591 /* ------------------------------------------------------------------------ */ 592 593 cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t in_ccache) 594 { 595 cc_int32 err = ccNoError; 596 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 597 k5_ipc_stream request = NULL; 598 k5_ipc_stream reply = NULL; 599 600 if (!in_ccache) { err = cci_check_error (ccErrBadParam); } 601 602 if (!err) { 603 err = krb5int_ipc_stream_new (&request); 604 } 605 606 if (!err) { 607 err = krb5int_ipc_stream_write_time (request, ccache->last_wait_for_change_time); 608 } 609 610 if (!err) { 611 err = cci_ipc_send (cci_ccache_wait_for_change_msg_id, 612 ccache->identifier, 613 request, 614 &reply); 615 } 616 617 if (!err) { 618 err = krb5int_ipc_stream_read_time (reply, &ccache->last_wait_for_change_time); 619 } 620 621 krb5int_ipc_stream_release (request); 622 krb5int_ipc_stream_release (reply); 623 624 return cci_check_error (err); 625 } 626 627 /* ------------------------------------------------------------------------ */ 628 629 cc_int32 ccapi_ccache_compare (cc_ccache_t in_ccache, 630 cc_ccache_t in_compare_to_ccache, 631 cc_uint32 *out_equal) 632 { 633 cc_int32 err = ccNoError; 634 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 635 cci_ccache_t compare_to_ccache = (cci_ccache_t) in_compare_to_ccache; 636 637 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 638 if (!in_compare_to_ccache) { err = cci_check_error (ccErrBadParam); } 639 if (!out_equal ) { err = cci_check_error (ccErrBadParam); } 640 641 if (!err) { 642 err = cci_identifier_compare (ccache->identifier, 643 compare_to_ccache->identifier, 644 out_equal); 645 } 646 647 return cci_check_error (err); 648 } 649 650 /* ------------------------------------------------------------------------ */ 651 652 cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t in_ccache, 653 cc_uint32 in_credentials_version, 654 cc_time_t *out_time_offset) 655 { 656 cc_int32 err = ccNoError; 657 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 658 k5_ipc_stream request = NULL; 659 k5_ipc_stream reply = NULL; 660 661 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 662 if (!out_time_offset) { err = cci_check_error (ccErrBadParam); } 663 664 if (!err) { 665 err = krb5int_ipc_stream_new (&request); 666 } 667 668 if (!err) { 669 err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); 670 } 671 672 if (!err) { 673 err = cci_ipc_send (cci_ccache_get_kdc_time_offset_msg_id, 674 ccache->identifier, 675 request, 676 &reply); 677 } 678 679 if (!err) { 680 err = krb5int_ipc_stream_read_time (reply, out_time_offset); 681 } 682 683 krb5int_ipc_stream_release (request); 684 krb5int_ipc_stream_release (reply); 685 686 return cci_check_error (err); 687 } 688 689 /* ------------------------------------------------------------------------ */ 690 691 cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache, 692 cc_uint32 in_credentials_version, 693 cc_time_t in_time_offset) 694 { 695 cc_int32 err = ccNoError; 696 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 697 k5_ipc_stream request = NULL; 698 699 if (!io_ccache) { err = cci_check_error (ccErrBadParam); } 700 701 if (!err) { 702 err = krb5int_ipc_stream_new (&request); 703 } 704 705 if (!err) { 706 err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); 707 } 708 709 if (!err) { 710 err = krb5int_ipc_stream_write_time (request, in_time_offset); 711 } 712 713 if (!err) { 714 err = cci_ipc_send (cci_ccache_set_kdc_time_offset_msg_id, 715 ccache->identifier, 716 request, 717 NULL); 718 } 719 720 krb5int_ipc_stream_release (request); 721 722 return cci_check_error (err); 723 } 724 725 /* ------------------------------------------------------------------------ */ 726 727 cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache, 728 cc_uint32 in_credentials_version) 729 { 730 cc_int32 err = ccNoError; 731 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 732 k5_ipc_stream request = NULL; 733 734 if (!io_ccache) { err = cci_check_error (ccErrBadParam); } 735 736 if (!err) { 737 err = krb5int_ipc_stream_new (&request); 738 } 739 740 if (!err) { 741 err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); 742 } 743 744 if (!err) { 745 err = cci_ipc_send (cci_ccache_clear_kdc_time_offset_msg_id, 746 ccache->identifier, 747 request, 748 NULL); 749 } 750 751 krb5int_ipc_stream_release (request); 752 753 return cci_check_error (err); 754 } 755 756 #ifdef TARGET_OS_MAC 757 #pragma mark - 758 #endif 759 760 /* ------------------------------------------------------------------------ */ 761 762 cc_int32 cci_ccache_get_compat_version (cc_ccache_t in_ccache, 763 cc_uint32 *out_compat_version) 764 { 765 cc_int32 err = ccNoError; 766 cci_ccache_t ccache = (cci_ccache_t) in_ccache; 767 768 if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } 769 if (!out_compat_version) { err = cci_check_error (ccErrBadParam); } 770 771 if (!err) { 772 *out_compat_version = ccache->compat_version; 773 } 774 775 return cci_check_error (err); 776 } 777 778 /* ------------------------------------------------------------------------ */ 779 780 cc_int32 cci_ccache_set_compat_version (cc_ccache_t io_ccache, 781 cc_uint32 in_compat_version) 782 { 783 cc_int32 err = ccNoError; 784 cci_ccache_t ccache = (cci_ccache_t) io_ccache; 785 786 if (!io_ccache) { err = cci_check_error (ccErrBadParam); } 787 788 if (!err) { 789 ccache->compat_version = in_compat_version; 790 } 791 792 return cci_check_error (err); 793 } 794