#include "dbinc.h" /***************************************************************************** * * * COMMON OCEANOGRAPHIC DATA ACCESS SYSTEM (CODAS) * * * * WRITTEN BY: RAMON CABRERA, ERIC FIRING, and JULIE RANADA * * JOINT INSTITUTE FOR MARINE AND ATMOSPHERIC RESEARCH * * 1000 POPE ROAD MSB 404 * * HONOLULU, HI 96822 * * * * VERSION: 3.00 * * * * DATE: APRIL 1989 * * * *****************************************************************************/ /* FILE: dbget.c SYSTEM FUNCTIONS FOR RETRIEVING DATA FROM AN EXISTING DATABASE */ /*----------------------------------------------------------------------------- FUNCTION: DBGET It retrieves data from the database into the user's buffer. PARAMETERS: type = pointer to data type data = address of user's buffer / on entrance, nb contains the number of bytes that the nb = / user's buffer can accomodate \ on exit, nb contains the actual number of bytes that \ have been stored in the user buffer ierr = pointer to error code RETURNS: VOID */ void DBGET(int *type, char *data, unsigned int *nb, int *ierr) { int nbytes; long ofs; STRUCT_DEF_HDR_TYPE *strdef; DATA_LIST_ENTRY_TYPE *data_list_entry; int dl_index; int i, ndle, nb_needed, len; SHORT access_t; DATA_LIST_ENTRY_TYPE dl_entry; if ( (*ierr = dbget_flags()) != 0 ) {*nb = 0; return;} /* ---> PROFILE DATA (types 0 - 99) */ if ( (*type >= 0) && (*type < (int)db_ptr->block_hdr.data_list_nentries) ) { if (!(db_ptr->profile_is_open)) {*ierr = NO_PROFILE_IS_OPEN; *nb = 0; return;} if (db_ptr->data_list[*type].access_type == UNUSED) {*ierr = INVALID_TYPE_REQUEST; *nb = 0; return;} if (*nb == 0) {get_access_param(type, nb, &ofs); return;} if (get_profile_data(type, data, nb)) goto error_found; } else if ( (*type >= 100) && (*type < 200) ) { switch (*type) { case DATASET_ID: if (*nb == 0) {*nb = sizeof(DATASET_ID_TYPE); return;} *nb = *nb >= sizeof(DATASET_ID_TYPE) ? sizeof(DATASET_ID_TYPE) : 0; move_byte((char *) &(db_ptr->block_hdr.dataset_id), data, *nb); break; case PRODUCER_ID: if (*nb == 0) {*nb = sizeof(PRODUCER_ID_TYPE); return;} *nb = *nb >= sizeof(PRODUCER_ID_TYPE) ? sizeof(PRODUCER_ID_TYPE) : 0; move_byte((char *) &(db_ptr->block_hdr.producer_id), data, *nb); break; case TIME: if (*nb == 0) {*nb = sizeof(YMDHMS_TIME_TYPE); return;} if (!(db_ptr->profile_is_open)) { *ierr = NO_PROFILE_IS_OPEN; *nb = 0; return; } *nb = *nb >= sizeof(YMDHMS_TIME_TYPE) ? sizeof(YMDHMS_TIME_TYPE) : 0; if (*nb) { if (db_ptr->block_hdr.dir_time_flag == DIR_TIME_IN_SECONDS) DIFTIM( (YMDHMS_TIME_TYPE *) &(db_ptr->block_base_time), (YMDHMS_TIME_TYPE *) data, (LONG *) &(db_ptr->profile_dir_entry_ptr->time) ); else HDIFTIM( (YMDHMS_TIME_TYPE *) &(db_ptr->block_base_time), (YMDHMS_TIME_TYPE *) data, (LONG *) &(db_ptr->profile_dir_entry_ptr->time) ); } break; case POSITION: if (*nb == 0) {*nb = 2 * sizeof(DMSH_POSITION_TYPE); return;} *nb = *nb >= 2 * sizeof(DMSH_POSITION_TYPE) ? 2 * sizeof(DMSH_POSITION_TYPE) : 0; if (*nb) *ierr = get_position((DMSH_POSITION_TYPE *) data); break; case DATA_MASK: if (*nb == 0) {*nb = sizeof(ULONG); return;} *nb = *nb >= sizeof(ULONG) ? sizeof(ULONG) : 0; move_byte((char *) &(db_ptr->block_hdr.data_mask), data, *nb); break; case DATA_PROC_MASK: if (*nb == 0) {*nb = sizeof(ULONG); return;} *nb = *nb >= sizeof(ULONG) ? sizeof(ULONG) : 0; move_byte((char *) &(db_ptr->block_hdr.data_proc_mask), data, *nb); break; case DEPTH_RANGE: if (*nb == 0) {*nb = sizeof(DEPTH_RANGE_TYPE); return;} *nb = *nb >= sizeof(DEPTH_RANGE_TYPE) ? sizeof(DEPTH_RANGE_TYPE) : 0; if (*nb) *ierr = get_depth_range((DEPTH_RANGE_TYPE *) data); break; default: *ierr = INVALID_TYPE_REQUEST; *nb = 0; break; } } else if ( (*type >= 200) && (*type < 300) ) { switch (*type) { case DATABASE_VERSION: if (*nb == 0) {*nb = 4; return;} *nb = *nb >= 4 ? 4 : 0; move_byte(db_ptr->block_hdr.db_version, data, *nb); break; case PRODUCER_HOST: if (*nb == 0) {*nb = 4; return;} *nb = *nb >= 4 ? 4 : 0; strncpy(data, db_ptr->block_hdr.producer_host, *nb); break; case DATABASE_NUMBER: if (*nb == 0) {*nb = sizeof(int); return;} *nb = *nb >= sizeof(int) ? sizeof(int) : 0; if (*nb) *((int *) data) = current_database + 1; break; case BLOCK_PROFILE_INDEX: if (*nb == 0) {*nb = 2 * sizeof(int); return;} *nb = *nb >= 2 * sizeof(int) ? 2 * sizeof(int) : 0; if (*nb) { move_byte((char *) &(db_ptr->block_dir_index), data, sizeof(int)); move_byte((char *) &(db_ptr->profile_dir_index), data + sizeof(int), sizeof(int)); } break; default: *ierr = INVALID_TYPE_REQUEST; *nb = 0; break; } } else if ( (*type >= 300) && (*type < 400) ) { switch (*type) { case BLOCK_DIR_FILE: if (*nb == 0) {*nb = strlen(db_ptr->block_dir_file); return;} *nb = *nb >= strlen(db_ptr->block_dir_file) ? strlen(db_ptr->block_dir_file) : 0; strcpy(data, db_ptr->block_dir_file); break; case BLOCK_FILE: if (*nb == 0) {*nb = strlen(db_ptr->block_file); return;} *nb = *nb >= strlen(db_ptr->block_file) ? strlen(db_ptr->block_file) : 0; strcpy(data, db_ptr->block_file); break; case BLOCK_DIR_HDR: if (*nb == 0) {*nb = BLOCK_DIR_HDR_SIZE; return;} *nb = *nb >= BLOCK_DIR_HDR_SIZE ? BLOCK_DIR_HDR_SIZE : 0; move_byte((char *) &(db_ptr->block_dir_hdr), data, *nb); break; case BLOCK_HDR: if (*nb == 0) {*nb = BLOCK_HDR_SIZE; return;} *nb = *nb >= BLOCK_HDR_SIZE ? BLOCK_HDR_SIZE : 0; move_byte((char *) &(db_ptr->block_hdr), data, *nb); break; case STRUCTURE_DEF: /* assumes "data" points to name of structure */ if (!db_ptr->block_strdef_loaded) if (load_block_strdef()) goto error_found; if ( (strdef = find_def(data, db_ptr->struct_def)) == NULL ) *ierr = STRUCTURE_NOT_PRESENT; else { nbytes = (1 + strdef->nelem) * sizeof(STRUCT_DEF_ENTRY_TYPE); if (*nb == 0) *nb = nbytes; /* query */ else { *nb = *nb >= nbytes ? nbytes : 0; move_byte((char *) strdef, data, *nb); } } break; case DATA_LIST_ENTRY: /* assumes data points to name of data */ nbytes = sizeof(DATA_LIST_ENTRY_TYPE); if (*nb == 0) *nb = nbytes; /* query */ else { /* I don't think we really need to check db_ptr->data_list_loaded at this point; if the database is open, there should be a an open block and therefore a data list. */ dl_index = get_data_list_index(data); if (dl_index < 0) { *ierr = INVALID_TYPE_REQUEST; *nb = 0; } data_list_entry = &(db_ptr->data_list[dl_index]); data_list_entry->index = dl_index; *nb = *nb >= nbytes ? nbytes : 0; move_byte((char *) data_list_entry, data, *nb); } break; case BLOCK_FTR: nbytes = db_ptr->block_hdr.block_ftr_ofs <= 0 ? 0 : (int)(db_ptr->block_hdr.block_nbytes - db_ptr->block_hdr.block_ftr_ofs); if (*nb == 0) {*nb = nbytes; return;} if (*nb > nbytes) *nb = nbytes; if (*nb > 0) { if ((db_ptr->error_code = read_data(db_ptr->fpblkdata, data, db_ptr->block_hdr.block_ftr_ofs, *nb)) != 0) { db_ptr->error_data = BLOCK_FTR; goto error_found; } /* block footer is of type text so we won't bother to do a platform check/conversion on it -- JR 95/07 */ } break; default: *ierr = INVALID_TYPE_REQUEST; *nb = 0; break; } } else /* >= 400 */ { switch (*type) { case DATA_LIST_NAMES: ndle = db_ptr->block_hdr.data_list_nentries; nb_needed = ndle * 20; if (*nb == 0) { *nb = nb_needed; return; } if (*nb < nb_needed) { *ierr = INSUFFICIENT_SPACE; *nb = 0; break; } for (i=0; idata_list[i]; access_t = dl_entry.access_type; if (access_t) { strcpy(data, dl_entry.name); len = strlen(dl_entry.name); data += len; data[0] = ' '; data++; } } data--; data[0] = NUL; *nb = strlen(data) + 1; break; case NAMES_WITH_DATA: ndle = db_ptr->block_hdr.data_list_nentries; nb_needed = ndle * 20; if (*nb == 0) { *nb = nb_needed; return; } if (*nb < nb_needed) { *ierr = INSUFFICIENT_SPACE; *nb = 0; break; } for (i=0; idata_list[i]; access_t = dl_entry.access_type; if (((access_t == 1) && (dl_entry.access_1 > 0)) || ((access_t == 2) && (db_ptr->data_dir[dl_entry.access_1].nbytes > 0))) { strcpy(data, dl_entry.name); len = strlen(dl_entry.name); data += len; data[0] = ' '; data++; } } data--; data[0] = NUL; *nb = strlen(data) + 1; break; default: *ierr = INVALID_TYPE_REQUEST; *nb = 0; break; } } return; error_found: report_db_error("DBGET"); *ierr = db_ptr->error_code * 1000 - db_ptr->error_data; } /*----------------------------------------------------------------------------- FUNCTION: get_profile_data It extracts user-defined data (types 0 to 99) from current profile if n > 0; if n = 0, it simply updates n to the number of bytes needed for that data type without retrieving the data. PARAMETERS: type = pointer to data type data = array to hold profile data user_nb = pointer to number of bytes that the user array can hold RETURNS: 0 if okay db_ptr->error_code otherwise */ int get_profile_data(int *type, char *data, unsigned int *user_nb) { unsigned int nb, nv; long ofs; get_access_param(type, &nb, &ofs); *user_nb = min_val(*user_nb, nb); if (*user_nb > 0) { if ((db_ptr->error_code = read_data(db_ptr->fpblkdata, data, ofs, *user_nb)) != 0) { db_ptr->error_data = PROFILE_DATA; goto error_found; } if (db_ptr->block_host != HOST_ENVIRONMENT) { if (db_ptr->data_list[*type].value_type == STRUCT_VALUE_CODE) { nv = -*user_nb; if (!db_ptr->block_strdef_loaded) if (load_block_strdef()) goto error_found; } else nv = *user_nb / VALUE_SIZE[db_ptr->data_list[*type].value_type]; if (convert_select(data, data, db_ptr->block_host, HOST_ENVIRONMENT, nv, db_ptr->data_list[*type].value_type, db_ptr->data_list[*type].name, db_ptr->struct_def) == BADUINT) { db_ptr->error_code = CONVERT_ERROR; db_ptr->error_data = *type; goto error_found; } } } return(0); error_found: *user_nb = 0; report_db_error("get_profile_data"); return(db_ptr->error_code); } /*----------------------------------------------------------------------------- FUNCTION: get_position It retrieves the position parameter for the current profile. PARAMETER: data = short integer array for storing latitude and longitude RETURNS: 0 if okay NO_PROFILE_IS_OPEN otherwise */ int get_position(DMSH_POSITION_TYPE *data) { int profile_key_type; profile_key_type = db_ptr->block_hdr.dir_type % 10; if ((profile_key_type == 0) || (profile_key_type == 2)) { HUNPOS(&data[0], &(db_ptr->block_hdr.lon1)); HUNPOS(&data[1], &(db_ptr->block_hdr.lat1)); } else if ((profile_key_type == 1) || (profile_key_type == 3)) { if (!(db_ptr->profile_is_open)) return(NO_PROFILE_IS_OPEN); HUNPOS(&data[0], &(db_ptr->profile_dir_entry_ptr->lon)); HUNPOS(&data[1], &(db_ptr->profile_dir_entry_ptr->lat)); } return(0); } /*----------------------------------------------------------------------------- FUNCTION: get_depth_range It retrieves the depth range parameter for the current profile. PARAMETER: data = short integer array for storing depth range RETURNS: 0 if okay NO_PROFILE_IS_OPEN otherwise */ int get_depth_range(DEPTH_RANGE_TYPE *data) { int profile_key_type; profile_key_type = db_ptr->block_hdr.dir_type % 10; if ((profile_key_type == 0) || (profile_key_type == 1)) { data->min_depth = db_ptr->block_hdr.depth1; data->max_depth = db_ptr->block_hdr.depth2; } else if ((profile_key_type == 2) || (profile_key_type == 3)) { if (!(db_ptr->profile_is_open)) return(NO_PROFILE_IS_OPEN); data->min_depth = db_ptr->profile_dir_entry_ptr->depth1; data->max_depth = db_ptr->profile_dir_entry_ptr->depth2; } return(0); }