#include <dce/ep.h>
#include <dsm.h>
#include <commonp.h>
#include <com.h>
#include <rpcdp.h>
#include <rpcddb.h>
typedef struct {
struct db *db_handle;
db_list_type_t list_type;
db_lists_t *lp;
unsigned32 pass;
} db_contexth_t, *db_contexth_p_t;
INTERNAL void list_add
(
db_list_t *list,
db_list_t *elp
);
INTERNAL void list_remove
(
db_list_t *list,
db_list_t *elp
);
INTERNAL boolean32 db_bad_context
(
struct db *h,
ept_lookup_handle_t *entry_handle
);
PRIVATE void db_open(h, database_file, version, status)
struct db *h;
unsigned char *database_file;
unsigned32 version;
error_status_t *status;
{
struct db_file_hdr hdr;
error_status_t tmp_st;
SET_STATUS_OK(status);
dsm_open(database_file, (dsm_handle_t *) &h->dsh, status);
if (STATUS_OK(status))
{
dsm_get_info(h->dsh,&hdr,sizeof(hdr),status);
if (! STATUS_OK(status))
{
if (dflag) show_st("Error reading endpoint database", status);
db_to_ept_ecode(status);
return;
}
if (hdr.version != version)
{
dsm_close((dsm_handle_t *) &h->dsh, &tmp_st);
h->dsh = NULL;
if (hdr.version < version)
{
remove((char *)database_file);
}
else
{
SET_STATUS(status, ept_s_database_invalid);
if (dflag) show_st("Newer persistent database version", status);
return;
}
}
else
h->object = hdr.object;
}
else
if (*status != dsm_err_open_failed)
{
if (dflag)
show_st("Error opening endpoint database", status);
db_to_ept_ecode(status);
return;
}
if (h->dsh == NULL)
{
dsm_create(database_file, (dsm_handle_t *) &h->dsh, status);
if (! STATUS_OK(status))
{
if (dflag)
show_st("Error creating endpoint database", status);
db_to_ept_ecode(status);
return;
}
uuid_create(&h->object, &tmp_st);
hdr.version = version;
hdr.object = h->object;
dsm_set_info(h->dsh, &hdr, sizeof(hdr), status);
if (! STATUS_OK(status))
{
if (dflag)
show_st("Error writing to endpoint database", status);
db_to_ept_ecode(status);
return;
}
}
return;
}
PRIVATE void db_update_entry(h, entp, status)
struct db *h;
db_entry_p_t entp;
error_status_t *status;
{
dsm_detach(h->dsh, (void *)entp, status);
if (! STATUS_OK(status)) return;
dsm_write(h->dsh, (void *)entp, status);
if (! STATUS_OK(status)) return;
}
INTERNAL unsigned32 db_c_object_list_offset;
INTERNAL unsigned32 db_c_interface_list_offset;
PRIVATE void db_init_lists(h)
struct db *h;
{
int i;
db_lists_mgmt_t *lists_mgmt;
db_lists_t lists;
lists_mgmt = &h->lists_mgmt;
lists_mgmt->entry_list.fwd = NULL;
lists_mgmt->entry_list.back = &lists_mgmt->entry_list;
for (i = 0; i < db_c_nbucket; i++)
{
lists_mgmt->object_table[i].fwd = NULL;
lists_mgmt->object_table[i].back = &lists_mgmt->object_table[i];
lists_mgmt->interface_table[i].fwd = NULL;
lists_mgmt->interface_table[i].back = &lists_mgmt->interface_table[i];
}
db_c_object_list_offset = ((char *) &lists.object_list) - ((char *) &lists.entry_list);
db_c_interface_list_offset = ((char *) &lists.interface_list) - ((char *) &lists.entry_list);
}
PRIVATE void db_lists_add(h, entp)
struct db *h;
db_entry_t *entp;
{
db_list_add(&h->lists_mgmt.entry_list, db_c_entry_list, (db_lists_t *) entp);
db_htable_add(h->lists_mgmt.object_table, db_c_object_list, &entp->object,
(db_lists_t *) entp);
db_htable_add(h->lists_mgmt.interface_table, db_c_interface_list, &entp->interface.uuid,
(db_lists_t *) entp);
}
PRIVATE void db_lists_remove(h, entp)
struct db *h;
db_entry_t *entp;
{
db_list_remove(&h->lists_mgmt.entry_list, db_c_entry_list, (db_lists_t *) entp);
db_htable_remove(h->lists_mgmt.object_table, db_c_object_list, &entp->object,
(db_lists_t *) entp);
db_htable_remove(h->lists_mgmt.interface_table, db_c_interface_list, &entp->interface.uuid,
(db_lists_t *) entp);
}
PRIVATE void db_htable_add(htable, table_type, id, entp)
db_hash_table_t htable;
db_list_type_t table_type;
uuid_p_t id;
db_lists_t *entp;
{
unsigned16 bucket;
error_status_t tmp_st;
bucket = uuid_hash(id, &tmp_st);
bucket = bucket % db_c_nbucket;
db_list_add(&htable[bucket], table_type, entp);
}
PRIVATE void db_htable_remove(htable, table_type, id, entp)
db_hash_table_t htable;
db_list_type_t table_type;
uuid_p_t id;
db_lists_t *entp;
{
unsigned16 bucket;
error_status_t tmp_st;
bucket = uuid_hash(id, &tmp_st);
bucket = bucket % db_c_nbucket;
db_list_remove(&htable[bucket], table_type, entp);
}
PRIVATE void db_list_add(list, list_type, entp)
db_list_t *list;
db_list_type_t list_type;
db_lists_t *entp;
{
db_list_t *elp;
error_status_t tmp_st;
switch(list_type)
{
case db_c_entry_list:
elp = &entp->entry_list;
break;
case db_c_object_list:
elp = &entp->object_list;
break;
case db_c_interface_list:
elp = &entp->interface_list;
break;
default:
tmp_st = ept_s_database_invalid;
show_st("db_list_add - bad list type", &tmp_st);
return;
}
list_add(list, elp);
}
PRIVATE void db_list_remove(list, list_type, entp)
db_list_t *list;
db_list_type_t list_type;
db_lists_t *entp;
{
db_list_t *elp;
error_status_t tmp_st;
switch(list_type)
{
case db_c_entry_list:
elp = &entp->entry_list;
break;
case db_c_object_list:
elp = &entp->object_list;
break;
case db_c_interface_list:
elp = &entp->interface_list;
break;
default:
tmp_st = ept_s_database_invalid;
show_st("db_list_remove - bad list type", &tmp_st);
return;
}
list_remove(list, elp);
}
INTERNAL void list_add(list, elp)
db_list_t *list;
db_list_t *elp;
{
elp->fwd = NULL;
elp->back = list->back;
elp->back->fwd = elp;
list->back = elp;
}
INTERNAL void list_remove(list, elp)
db_list_t *list;
db_list_t *elp;
{
elp->back->fwd = elp->fwd;
if (elp->fwd != NULL)
elp->fwd->back = elp->back;
else
list->back = elp->back;
elp->fwd = NULL;
elp->back = NULL;
}
PRIVATE db_lists_t *db_list_first(lists_mgmt, list_type, id)
db_lists_mgmt_t *lists_mgmt;
db_list_type_t list_type;
uuid_p_t id;
{
unsigned16 bucket;
error_status_t tmp_st;
db_list_t *elp;
db_lists_t *entp;
entp = NULL;
switch(list_type)
{
case db_c_entry_list:
entp = (db_lists_t *) lists_mgmt->entry_list.fwd;
break;
case db_c_object_list:
bucket = uuid_hash(id, &tmp_st);
bucket = bucket % db_c_nbucket;
elp = lists_mgmt->object_table[bucket].fwd;
if (elp != NULL)
entp = (db_lists_t *) (((char *) elp) - db_c_object_list_offset);
break;
case db_c_interface_list:
bucket = uuid_hash(id, &tmp_st);
bucket = bucket % db_c_nbucket;
elp = lists_mgmt->interface_table[bucket].fwd;
if (elp != NULL)
entp = (db_lists_t *) (((char *) elp) - db_c_interface_list_offset);
break;
default:
tmp_st = ept_s_database_invalid;
show_st("db_list_first - bad list type", &tmp_st);
break;
}
return(entp);
}
PRIVATE db_lists_t *db_list_next(list_type, xentp)
db_list_type_t list_type;
db_lists_t *xentp;
{
db_list_t *elp;
db_lists_t *entp;
error_status_t tmp_st;
entp = NULL;
switch(list_type)
{
case db_c_entry_list:
entp = (db_lists_t *) xentp->entry_list.fwd;
break;
case db_c_object_list:
elp = xentp->object_list.fwd;
if (elp != NULL)
entp = (db_lists_t *) (((char *) elp) - db_c_object_list_offset);
break;
case db_c_interface_list:
elp = xentp->interface_list.fwd;
if (elp != NULL)
entp = (db_lists_t *) (((char *) elp) - db_c_interface_list_offset);
break;
default:
tmp_st = ept_s_database_invalid;
show_st("db_list_next - bad list type", &tmp_st);
break;
}
return(entp);
}
PRIVATE void db_save_context(h, entry_handle, list_type, lp, pass)
struct db *h;
ept_lookup_handle_t *entry_handle;
db_list_type_t list_type;
db_lists_t *lp;
unsigned32 pass;
{
db_contexth_t *chp;
db_entry_t *entp;
if (lp == NULL)
{
db_delete_context(h, entry_handle);
return;
}
if (db_bad_context(h, entry_handle))
return;
if (*entry_handle != NULL)
{
chp = (db_contexth_t *) (*entry_handle);
entp = (db_entry_t *) chp->lp;
entp->read_nrefs--;
}
else
{
*entry_handle = (ept_lookup_handle_t *) malloc(sizeof(db_contexth_t));
if (*entry_handle == NULL)
return;
chp = (db_contexth_t *) (*entry_handle);
}
entp = (db_entry_t *) lp;
entp->read_nrefs++;
if (entp->read_nrefs >= db_c_max_read_nrefs)
{
db_delete_context(h, entry_handle);
return;
}
chp->db_handle = h;
chp->list_type = list_type;
chp->lp = lp;
chp->pass = pass;
}
PRIVATE void db_delete_context(h, entry_handle)
struct db *h;
ept_lookup_handle_t *entry_handle;
{
db_contexth_t *chp;
db_entry_t *entp;
if (db_bad_context(h, entry_handle) || (*entry_handle == NULL))
return;
chp = (db_contexth_t *) (*entry_handle);
entp = (db_entry_t *) chp->lp;
entp->read_nrefs--;
free(chp);
*entry_handle = NULL;
}
PRIVATE void db_get_context(h, entry_handle, list_type, lp, pass, status)
struct db *h;
ept_lookup_handle_t *entry_handle;
db_list_type_t *list_type;
db_lists_t **lp;
unsigned32 *pass;
error_status_t *status;
{
db_contexth_t *chp;
if (db_bad_context(h, entry_handle) || (*entry_handle == NULL))
{
SET_STATUS(status, ept_s_invalid_context);
return;
}
chp = (db_contexth_t *) *entry_handle;
*list_type = chp->list_type;
*lp = chp->lp;
*pass = chp->pass;
SET_STATUS_OK(status);
}
PRIVATE boolean32 db_different_context(h, entry_handle, status)
struct db *h;
ept_lookup_handle_t *entry_handle;
error_status_t *status;
{
db_contexth_t *chp;
SET_STATUS_OK(status);
if (entry_handle == NULL)
return(false);
if (*entry_handle != NULL)
{
chp = (db_contexth_t *) *entry_handle;
if (chp->db_handle != h)
{
SET_STATUS(status, ept_s_invalid_context);
return(true);
}
}
return(false);
}
INTERNAL boolean32 db_bad_context(h, entry_handle)
struct db *h;
ept_lookup_handle_t *entry_handle;
{
db_contexth_t *chp;
if (entry_handle == NULL)
return(true);
if (*entry_handle != NULL)
{
chp = (db_contexth_t *) *entry_handle;
if (chp->db_handle != h)
return(true);
}
return(false);
}
PRIVATE void db_lock(h)
struct db *h;
{
dcethread_mutex_lock_throw(&h->lock);
}
PRIVATE void db_unlock(h)
struct db *h;
{
dcethread_mutex_unlock_throw(&h->lock);
}
PRIVATE void db_init_lock(h)
struct db *h;
{
dcethread_mutex_init_throw(&h->lock, NULL);
}
PRIVATE void db_to_ept_ecode(status)
error_status_t *status;
{
switch ((int)*status)
{
case dsm_err_create_failed:
*status = ept_s_cant_create;
break;
case dsm_err_file_io_error:
*status = ept_s_update_failed;
break;
case dsm_err_open_failed:
*status = ept_s_cant_access;
break;
case dsm_err_version:
*status = ept_s_database_invalid;
break;
case dsm_err_no_memory:
*status = ept_s_no_memory;
break;
case dsm_err_duplicate_write:
*status = ept_s_update_failed;
break;
case dsm_err_header_too_long:
*status = ept_s_database_invalid;
break;
case dsm_err_no_more_entries:
*status = ept_s_not_registered;
break;
case dsm_err_invalid_handle:
*status = ept_s_cant_perform_op;
break;
case dsm_err_invalid_pointer:
*status = ept_s_cant_perform_op;
break;
case dsm_err_info_too_long:
*status = ept_s_cant_perform_op;
break;
case dsm_err_file_busy:
*status = ept_s_database_already_open;
break;
case dsm_err_invalid_marker:
*status = ept_s_cant_perform_op;
break;
default:
break;
}
}