/****************************************************************************** FILE: mkblkdir.c USAGE: mkblkdir This file contains a set of routines for reconstructing a CODAS directory file from a set of block files. It requires a control file that provides the name for the reconstructed CODAS database, the name of the producer definition file to be used, optionally the name(s) of structure definition file(s) that define user-defined structures in the database in case these were not loaded with the block file, and the names of the block files that will be included in this database. See the file mkblkdir.cnt for an example. Eric Firing 88-01-16 *****************************************************************************/ #include "dbinc.h" #include "ioserv.h" #include "mc.h" int do_loadsd(FILE *fp, char *arg, int code); int do_add_block_file(FILE *fp, char *arg, int code); char *add_block_file(FILE_NAME_TYPE fn_old_block); void dbcreate(); static FILE_NAME_TYPE db_name, prd_name; static DATASET_ID_TYPE dataset_id; static char dest[40], block_dir_type[2]; static int DestMachine; static OPTION_TYPE options2[] = { {"end" , 0, NULL , (char *) NULL}, {"SD_NAME" , 0, do_loadsd , (char *) NULL}, {"BLOCK_FILE" , 0, do_add_block_file, (char *) NULL}, {NULL , 0, NULL , (char *) NULL} }; static OPTION_TYPE options1[] = { {"end" , 0 , NULL , (char *) NULL}, {"DB_NAME" , TYPE_STRING, op_get_param, db_name}, {"PRD_NAME" , TYPE_STRING, op_get_param, prd_name}, {"DATASET_ID" , TYPE_STRING, op_get_param, (char *) &dataset_id}, {"BLOCK_DIR_TYPE", TYPE_STRING, op_get_param, block_dir_type}, {"DESTINATION", TYPE_STRING, op_get_param, dest}, {NULL , 0 , NULL , (char *) NULL} }; NAME_LIST_ENTRY_TYPE hosts[] = { {"PC_COMPATIBLE_HOST" , 0}, {"VAXD_COMPATIBLE_HOST", 1}, {"SUN3_COMPATIBLE_HOST", 2}, {NULL , -1} }; int main(int argc, char *argv[]) { int db_id = 1; int im = 0; int ier; FILE *fp_cnt; fp_cnt = get_fpcnt(argc, argv); /* initialize options to defaults */ strcpy(db_name, ""); strcpy(prd_name, ""); strcpy(dataset_id.instrument_name, ""); strcpy(block_dir_type, ""); DestMachine = HOST_ENVIRONMENT; if (execute_options(fp_cnt, options1, ECHO) < 0) return 1; fflush(stdout); if (!strcmp(db_name, "")) { fprintf(stderr, "\n ERROR: Missing DB_NAME in control file\n\n"); return 1; } if (strcmp(prd_name, "") && (strcmp(dataset_id.instrument_name, "") || strcmp(block_dir_type, "")) ) { /* can't have both PRD_NAME and DATASET_ID, etc. in control file */ fprintf(stderr, "\n ERROR: A PRD_NAME or\n"); fprintf(stderr, "\n DATASET_ID, PRODUCER_ID and BLOCK_DIR_TYPE must be specified.\n\n"); return 1; } if ( (!strcmp(prd_name, "") && (!strcmp(dataset_id.instrument_name, "") || !strcmp(block_dir_type, "")) )) { /* if both PRD_NAME and DATASET_ID, etc. not given, set up some defaults */ strcpy(dataset_id.instrument_name, "ADCP-VM"); strcpy(block_dir_type, "0"); } if (strcmp(dest, "") && (DestMachine = get_code(hosts, dest)) == BADINT) { fprintf(stderr, "\n ERROR: Unrecognized destination %s\n\n", dest); return 1; } dbcreate(&db_id, db_name, prd_name, &im, &ier); if (DBERROR(&ier, "in DBCREATE")) return 1; execute_options(fp_cnt, options2, ECHO); DBCLOSE(&ier); if (DBERROR(&ier, "in DBCLOSE")) return 1; if (DestMachine != HOST_ENVIRONMENT) convert_block_dir(db_name, DestMachine); puts("\n"); return 0; } int do_loadsd(FILE *fp, char *arg, int code) { int ier = 0; FILE_NAME_TYPE sd_name; if (!getword_nc(fp, sd_name, sizeof(FILE_NAME_TYPE))) { printf("\n ERROR: Scanning control file for structure definition file name\n"); return(-1); } DBLOADSD(sd_name, &ier); if (DBERROR(&ier, "in DBLOADSD")) return(-1); return(0); } int do_add_block_file(FILE *fp, char *arg, int code) { FILE_NAME_TYPE fn_old_block; char *fn_new_block; if (!getword_nc(fp, fn_old_block, sizeof(FILE_NAME_TYPE))) { printf("\n ERROR: Scanning control file for block file name\n"); return(-1); } fn_new_block = add_block_file(fn_old_block); if (fn_new_block == NULL) { printf("\n ERROR: Adding block file = %s", fn_old_block); return(-1); } printf(" %s ---> %s", fn_old_block, fn_new_block); return(0); } /*----------------------------------------------------------------------------- FUNCTION: copy_file This does a rather slow byte-by-byte binary file copy. ARGUMENTS: fn_from source file name fn_to destination file name RETURNS: 0 if successful, EOF otherwise. */ int copy_file(char *fn_from, char *fn_to) { FILE *fp_from, *fp_to; char c; if ( (fp_from = fopen(fn_from, "rb")) == NULL ) return EOF; if ( (fp_to = fopen(fn_to, "wb")) == NULL ) return EOF; #define VBUFSIZE 8192 if (setvbuf(fp_from, NULL, _IOFBF, VBUFSIZE) || setvbuf(fp_to , NULL, _IOFBF, VBUFSIZE)) { printf("\n ERROR: Cannot set up buffers for file copy\n\n"); return(EOF); } c = fgetc(fp_from); while (!feof(fp_from)) { fputc(c, fp_to); c = fgetc(fp_from); } fclose(fp_to); fclose(fp_from); return(0); } /*---------------------------------------------------------- FUNCTION: add_block_file This is for adding an existing block file to a database opened with DBCREATE. The intended applications are the construction of new working databases from a conglomeration of data blocks, the reconstruction of lost or damaged block directories, and the construction of block directories with data blocks that have been transferred and need to be translated from one machine to another. ARGUMENT: file name of the block file to be added. RETURNS: pointer to the name of the new block file, if successful; NULL otherwise. */ char *add_block_file(FILE_NAME_TYPE fn_old_block) { FILE *fp_new_block; int from; /* ---> Set up a block directory entry and set the file ID. */ if (create_block_dir_entry()) goto error_found; /* ---> SET NAME OF BLOCK FILE */ sprintf( (db_ptr->block_file+db_ptr->path_nchar), db_ptr->block_dir_hdr.block_file_template, db_ptr->block_dir_entry_ptr->file_id); if (!EXISTS(db_ptr->block_file)) { if ( (db_ptr->error_code = convert_block_file(fn_old_block, db_ptr->block_file, DestMachine)) != 0 ) /* jr */ { printf("\n ERROR: Copying %s to %s", fn_old_block, db_ptr->block_file); goto error_found; } } else { if (stricmp(fn_old_block, db_ptr->block_file) != 0) /* ---> If a file with the new name exists, but this name is not the same as that of the current old block file, then there is a danger that the old file names may be out of sequence, or for some other reason we may be in danger of accidentally overwriting a block file. The file name comparison is done without case sensitivity. Fri 09-08-1995 */ { printf("\n ERROR in add_block_file: New file name duplicates"); printf("\n an old one, but the files do not correspond.\n"); goto error_found; } else { if ( (fp_new_block = fopen(db_ptr->block_file, "rb")) == NULL ) { printf("\n ERROR: Can't open %s\n", db_ptr->block_file); goto error_found; } fread(&(db_ptr->block_hdr), BLOCK_HDR_SIZE, 1, fp_new_block); fclose(fp_new_block); if ((from = identify_ms_code(db_ptr->block_hdr.ms_code)) == UNKNOWN_HOST) { db_ptr->error_code = UNKNOWN_HOST_ERROR; db_ptr->error_data = BLOCK_HDR; goto error_found; } if (from != DestMachine) { printf("\n ERROR in add_block_file: In-place platform"); printf("\n conversion not allowed at this time.\n"); goto error_found; } } } update_block_dir_entry(); if (add_block_dir_entry()) goto error_found; db_ptr->new_block_is_open = 0; db_ptr->block_dir_modified = 1; return(db_ptr->block_file); error_found: report_db_error("add_block_file"); return(NULL); } /*----------------------------------------------------------------------------- FUNCTION: dbcreate It opens a new or existing database for appending. This version is modified from the dbsource/dbcreate.c version in that it does not have to load the producer definition from an external file; instead it just reads the 3 items it needs from the user's control file: DATASET_ID, PRODUCER_ID and BLOCK_DIR_TYPE. PARAMETERS: db_id = pointer to database number db_name = pointer to database name, including path; replaced by name without path. prd_name = pointer to name of producer definition file memory_mode = pointer to memory mode for directories ierr = pointer to error code RETURNS: VOID */ void dbcreate(int *db_id, char *db_name, char *prd_name, int *memory_mode, int *ierr) { int i, id; FILE_NAME_TYPE path_name, path, db_root; char answ[2]; *ierr = 0; if ((*ierr = alignment_check()) != 0) return; /**jr++**/ if (first_database_call) { for (i = 0; i < MAX_OPEN_DATABASES; i++) database_table[i] = NULL; first_database_call = 0; } id = *db_id - 1; if ((id < 0) || (id >= MAX_OPEN_DATABASES)) { *ierr = INVALID_DATABASE_NUMBER; return; } if (database_table[id]) { db_ptr = database_table[id]; *ierr = DB_ALREADY_OPEN; return; } if ((database_table[id] = (DATABASE_TYPE *) malloc(DATABASE_SIZE)) == NULL) { db_ptr->error_code = INSUFFICIENT_MEMORY; db_ptr->error_data = BLOCK_DIR; goto error_found; } current_database = id; db_ptr = database_table[id]; set_byte((UBYTE *)db_ptr, 0, DATABASE_SIZE); if (*memory_mode) db_ptr->memory_directory = 1; else db_ptr->memory_directory = 0; strtrim(path_name, db_name, sizeof(FILE_NAME_TYPE)); if (strlen(path_name) + 8 > sizeof(FILE_NAME_TYPE)) { /* need 8 char for file number, ext, NUL */ *ierr = PATHNAME_TOO_LONG; return; } split_path(path_name, path, db_root); if (strlen(db_root) > MAX_DBNAME_LENGTH) { *ierr = DBNAME_TOO_LONG; return; } db_ptr->path_nchar = strlen(path); strcpy(db_ptr->block_dir_hdr.block_file_template, db_root); strcat(db_ptr->block_dir_hdr.block_file_template, "%03u.blk"); strcpy(db_ptr->block_file, path); strcpy(db_ptr->block_dir_file, path); strcat(db_ptr->block_dir_file, db_root); strcat(db_ptr->block_dir_file, "dir.blk"); /* ---> ALLOCATE MEMORY FOR PRODUCER DEFINITION */ if ((db_ptr->producer = (PRODUCER_DEFINITION_TYPE *) malloc(sizeof(PRODUCER_DEFINITION_TYPE))) == NULL) { db_ptr->error_code = INSUFFICIENT_MEMORY; db_ptr->error_data = PRODUCER_DEF; goto error_found; } db_ptr->producer_in_memory = 1; set_byte((UBYTE *)db_ptr->producer, '\0', sizeof(PRODUCER_DEFINITION_TYPE)); if (strcmp(prd_name, "")) { strtrim(db_ptr->producer_def_file, prd_name, sizeof(FILE_NAME_TYPE)); if (load_producer_definition()) goto error_found; } else { strncpy((char *) &db_ptr->producer->dataset_id, (char *) &dataset_id, sizeof(DATASET_ID_TYPE)); db_ptr->producer->block_dir_type = atol(block_dir_type); } db_ptr->access_mode = READ_WRITE; db_ptr->create_mode = 1; if (EXISTS(db_ptr->block_dir_file)) { fprintf(stdout, "\n ERROR: File %s already exists! Overwrite? ", db_ptr->block_dir_file); scanf(" %2s", answ); if (answ[0] == 'n') { db_ptr->error_code = FILE_PROTECTION_ERROR; db_ptr->error_data = BLOCK_DIR_FILE; goto error_found; } } if (create_block_dir()) goto error_found; if (open_block_dir()) goto error_found; if (db_ptr->memory_directory) { if (allocate_memory_for_directories()) goto error_found; if (db_ptr->block_dir_hdr.dir_nentries) { if (load_block_dir()) goto error_found; } } db_ptr->block_dir_loaded = 1; return; error_found: report_db_error("dbcreate"); *ierr = db_ptr->error_code * 1000 - db_ptr->error_data; release_database(); }