/* mupfndfil.c * Description: * For a region find if the corresponding database is present. * Arguments: * reg: Region's pointer * filestr: Sent as allocated memory, if returned full path is needed in this mstr * Returns: TRUE if region's database file is found * FALSE, otherwise * Side Effects: * reg->dyn.addr->fname_len and reg->dyn.addr->fname are updated */ boolean_t mupfndfil(gd_region *reg, mstr *filestr) { char filename[MAX_FN_LEN]; mstr file, def, ret, *retptr; uint4 ustatus; switch(reg->dyn.addr->acc_meth) { case dba_mm: case dba_bg: break; # ifdef VMS case dba_usr: gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_NOUSERDB, 4, LEN_AND_LIT("specified function"), REG_LEN_STR(reg)); return FALSE; /* This is currently a VMS only possibility and has no corresponding test case */ # endif default: util_out_print("REGION !AD has an unrecognized access method.", TRUE, REG_LEN_STR(reg)); return FALSE; } file.addr = (char *)reg->dyn.addr->fname; file.len = reg->dyn.addr->fname_len; #if defined(UNIX) file.addr[file.len] = 0; if (is_raw_dev(file.addr)) { def.addr = DEF_NODBEXT; def.len = SIZEOF(DEF_NODBEXT) - 1; } else { def.addr = DEF_DBEXT; /* UNIX need to pass "*.dat" but reg->dyn.addr->defext has "DAT" */ def.len = SIZEOF(DEF_DBEXT) - 1; } #elif defined(VMS) def.addr = (char *)reg->dyn.addr->defext; def.len = SIZEOF(reg->dyn.addr->defext); #endif if (NULL == filestr) { ret.len = SIZEOF(filename); ret.addr = filename; retptr = &ret; } else retptr = filestr; if (FILE_PRESENT != gtm_file_stat(&file, &def, retptr, FALSE, &ustatus)) { if (!jgbl.mupip_journal) { /* Do not print error messages in case of call from mur_open_files(). * Currently we use "jgbl.mupip_journal" to identify a call from mupip_recover code */ util_out_print("REGION !AD's file !AD cannot be found.", TRUE, REG_LEN_STR(reg), LEN_AND_STR(file.addr)); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ustatus); } return FALSE; } reg->dyn.addr->fname_len = retptr->len; memcpy(reg->dyn.addr->fname, retptr->addr, retptr->len + 1); return TRUE; }
bool reg_cmcheck(gd_region *reg) { gd_segment *seg; char fbuff[MAX_FBUFF + 1]; parse_blk pblk; mstr file; int status; error_def(ERR_DBFILERR); seg = reg->dyn.addr; file.addr = (char *)seg->fname; file.len = seg->fname_len; memset(&pblk, 0, sizeof(pblk)); pblk.buffer = fbuff; pblk.buff_size = MAX_FBUFF; pblk.fop = (F_SYNTAXO | F_PARNODE); strncpy(fbuff,file.addr,file.len); *(fbuff + file.len) = '\0'; if (is_raw_dev(fbuff)) { pblk.def1_buf = DEF_NODBEXT; pblk.def1_size = sizeof(DEF_NODBEXT) - 1; } else { pblk.def1_buf = DEF_DBEXT; pblk.def1_size = sizeof(DEF_DBEXT) - 1; } status = parse_file(&file, &pblk); if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_DBFILERR,2, seg->fname_len, seg->fname, status); assert((int)pblk.b_esl + 1 <= sizeof(seg->fname)); memcpy(seg->fname, pblk.buffer, pblk.b_esl); pblk.buffer[pblk.b_esl] = 0; seg->fname[pblk.b_esl] = 0; seg->fname_len = pblk.b_esl; if (pblk.fnb & F_HAS_NODE) { assert(pblk.b_node && ':' == pblk.l_node[pblk.b_node - 1]); return TRUE; } return FALSE; }
gd_region *dbfilopn (gd_region *reg) { unix_db_info *udi; parse_blk pblk; mstr file; char *fnptr, fbuff[MAX_FBUFF + 1]; struct stat buf; gd_region *prev_reg; gd_segment *seg; int status; bool raw; int stat_res; seg = reg->dyn.addr; assert(seg->acc_meth == dba_bg || seg->acc_meth == dba_mm); if (NULL == seg->file_cntl) { seg->file_cntl = (file_control *)malloc(sizeof(*seg->file_cntl)); memset(seg->file_cntl, 0, sizeof(*seg->file_cntl)); } if (NULL == seg->file_cntl->file_info) { seg->file_cntl->file_info = (void *)malloc(sizeof(unix_db_info)); memset(seg->file_cntl->file_info, 0, sizeof(unix_db_info)); } file.addr = (char *)seg->fname; file.len = seg->fname_len; memset(&pblk, 0, sizeof(pblk)); pblk.buffer = fbuff; pblk.buff_size = MAX_FBUFF; pblk.fop = (F_SYNTAXO | F_PARNODE); memcpy(fbuff,file.addr,file.len); *(fbuff + file.len) = '\0'; if (is_raw_dev(fbuff)) { raw = TRUE; pblk.def1_buf = DEF_NODBEXT; pblk.def1_size = sizeof(DEF_NODBEXT) - 1; } else { raw = FALSE; pblk.def1_buf = DEF_DBEXT; pblk.def1_size = sizeof(DEF_DBEXT) - 1; } status = parse_file(&file, &pblk); if (!(status & 1)) { if (GTCM_GNP_SERVER_IMAGE != image_type) { free(seg->file_cntl->file_info); free(seg->file_cntl); seg->file_cntl = 0; } rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status); } assert(pblk.b_esl < sizeof(seg->fname)); memcpy(seg->fname, pblk.buffer, pblk.b_esl); pblk.buffer[pblk.b_esl] = 0; seg->fname[pblk.b_esl] = 0; seg->fname_len = pblk.b_esl; if (pblk.fnb & F_HAS_NODE) { /* Remote node specification given */ assert(pblk.b_node && pblk.l_node[pblk.b_node - 1] == ':'); gvcmy_open(reg, &pblk); return (gd_region *)-1; } fnptr = (char *)seg->fname + pblk.b_node; udi = FILE_INFO(reg); udi->raw = raw; udi->fn = (char *)fnptr; OPENFILE(fnptr, O_RDWR, udi->fd); udi->ftok_semid = INVALID_SEMID; udi->semid = INVALID_SEMID; udi->shmid = INVALID_SHMID; udi->sem_ctime = 0; udi->shm_ctime = 0; reg->read_only = FALSE; /* maintain csa->read_write simultaneously */ udi->s_addrs.read_write = TRUE; /* maintain reg->read_only simultaneously */ if (udi->fd == -1) { OPENFILE(fnptr, O_RDONLY, udi->fd); if (udi->fd == -1) { errno_save = errno; if (GTCM_GNP_SERVER_IMAGE != image_type) { free(seg->file_cntl->file_info); free(seg->file_cntl); seg->file_cntl = 0; } rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), errno_save); } reg->read_only = TRUE; /* maintain csa->read_write simultaneously */ udi->s_addrs.read_write = FALSE; /* maintain reg->read_only simultaneously */ } STAT_FILE(fnptr, &buf, stat_res); set_gdid_from_stat(&udi->fileid, &buf); if (prev_reg = gv_match(reg)) { close(udi->fd); free(seg->file_cntl->file_info); free(seg->file_cntl); seg->file_cntl = 0; return prev_reg; } return reg; }
gld_dbname_list *read_db_files_from_gld(gd_addr *addr) { gd_segment *seg; uint4 ustatus; gd_region *map_region; gd_region *map_region_top; gld_dbname_list head, *dblist = &head; char filename[MAX_FN_LEN]; mstr file, def, ret, *retptr; error_def(ERR_FILENOTFND); head.next = NULL; for (map_region = addr->regions, map_region_top = map_region + addr->n_regions; map_region < map_region_top; map_region++) { assert (map_region < map_region_top); seg = (gd_segment *)map_region->dyn.addr; if (NULL == seg->file_cntl) { seg->file_cntl = (file_control *)malloc(sizeof(*seg->file_cntl)); memset(seg->file_cntl, 0, sizeof(*seg->file_cntl)); } if (NULL == seg->file_cntl->file_info) { seg->file_cntl->file_info = (void *)malloc(sizeof(GDS_INFO)); memset(seg->file_cntl->file_info, 0, sizeof(GDS_INFO)); } ret.len = sizeof(filename); ret.addr = filename; retptr = &ret; file.addr = (char *)seg->fname; file.len = seg->fname_len; #if defined(UNIX) file.addr[file.len] = 0; if (is_raw_dev(file.addr)) { def.addr = DEF_NODBEXT; def.len = sizeof(DEF_NODBEXT) - 1; } else { def.addr = DEF_DBEXT; /* UNIX need to pass "*.dat" but reg->dyn.addr->defext has "DAT" */ def.len = sizeof(DEF_DBEXT) - 1; } #elif defined(VMS) def.addr = DEFDBEXT; def.len = sizeof(DEFDBEXT) - 1; #endif if (FILE_PRESENT != gtm_file_stat(&file, &def, retptr, FALSE, &ustatus)) { gtm_putmsg(VARLSTCNT(5) ERR_FILENOTFND, 2, file.len, file.addr, ustatus); return NULL; } assert(0 == filename[retptr->len]); seg->fname_len = retptr->len; memcpy(seg->fname, filename, retptr->len + 1); dblist = dblist->next = (gld_dbname_list *)malloc(sizeof(gld_dbname_list)); memset(dblist, 0, sizeof(gld_dbname_list)); map_region->stat.addr = (void *)dblist; dblist->gd = map_region; } return head.next; }
unsigned char mu_cre_file(void) { char *cc = NULL, path[MAX_FBUFF + 1], errbuff[512]; unsigned char buff[DISK_BLOCK_SIZE]; int fd = -1, i, lower, upper, status, padded_len, padded_vbn, norm_vbn; uint4 raw_dev_size; /* size of a raw device, in bytes */ int4 blocks_for_create, blocks_for_extension, save_errno; GTM_BAVAIL_TYPE avail_blocks; file_control fc; mstr file; parse_blk pblk; unix_db_info udi_struct, *udi; char *fgets_res; gd_segment *seg; error_def(ERR_NOSPACECRE); error_def(ERR_LOWSPACECRE); assert((-(sizeof(uint4) * 2) & sizeof(sgmnt_data)) == sizeof(sgmnt_data)); cs_addrs = &udi_struct.s_addrs; cs_data = (sgmnt_data_ptr_t)NULL; /* for CLEANUP */ memset(&pblk, 0, sizeof(pblk)); pblk.fop = (F_SYNTAXO | F_PARNODE); pblk.buffer = path; pblk.buff_size = MAX_FBUFF; file.addr = (char*)gv_cur_region->dyn.addr->fname; file.len = gv_cur_region->dyn.addr->fname_len; strncpy(path,file.addr,file.len); *(path+file.len) = '\0'; if (is_raw_dev(path)) { /* do not use a default extension for raw device files */ pblk.def1_buf = DEF_NODBEXT; pblk.def1_size = sizeof(DEF_NODBEXT) - 1; } else { pblk.def1_buf = DEF_DBEXT; pblk.def1_size = sizeof(DEF_DBEXT) - 1; } if (1 != (parse_file(&file, &pblk) & 1)) { PRINTF("Error translating filename %s.\n", gv_cur_region->dyn.addr->fname); return EXIT_ERR; } path[pblk.b_esl] = 0; if (pblk.fnb & F_HAS_NODE) { /* Remote node specification given */ assert(pblk.b_node); PRINTF("Database file for region %s not created; cannot create across network.\n", path); return EXIT_WRN; } udi = &udi_struct; udi->raw = is_raw_dev(pblk.l_dir); if (udi->raw) { fd = OPEN(pblk.l_dir,O_EXCL | O_RDWR); if (-1 == fd) { SPRINTF_AND_PERROR("Error opening file %s\n"); return EXIT_ERR; } if (-1 != (status = (ssize_t)lseek(fd, 0, SEEK_SET))) { DOREADRC(fd, buff, sizeof(buff), status); } else status = errno; if (0 != status) { SPRINTF_AND_PERROR("Error reading header for file %s\n"); return EXIT_ERR; } if (!memcmp(buff, GDS_LABEL, STR_LIT_LEN(GDS_LABEL))) { char rsp[80]; PRINTF("Database already exists on device %s\n", path); PRINTF("Do you wish to re-initialize (all current data will be lost) [y/n] ? "); FGETS(rsp, 79, stdin, fgets_res); if ('y' != *rsp) return EXIT_NRM; } PRINTF("Determining size of raw device...\n"); for(i = 1; read(fd, buff, sizeof(buff)) == sizeof(buff);) { i *= 2; lseek(fd, (off_t)i * BUFSIZ, SEEK_SET); } lower = i / 2; upper = i; while ((lower + upper) / 2 != lower) { i = (lower + upper) / 2; lseek(fd, (off_t)i * BUFSIZ, SEEK_SET); if (read(fd, buff, sizeof(buff)) == sizeof(buff)) lower = i; else upper = i; } raw_dev_size = i * BUFSIZ; } else { fd = OPEN3(pblk.l_dir, O_CREAT | O_EXCL | O_RDWR, 0600); if (-1 == fd) { SPRINTF_AND_PERROR("Error opening file %s\n"); return EXIT_ERR; } if (0 != (save_errno = disk_block_available(fd, &avail_blocks, FALSE))) { errno = save_errno; SPRINTF_AND_PERROR("Error checking available disk space for %s\n"); CLEANUP(EXIT_ERR); return EXIT_ERR; } seg = gv_cur_region->dyn.addr; /* blocks_for_create is in the unit of DISK_BLOCK_SIZE */ blocks_for_create = DIVIDE_ROUND_UP(sizeof(sgmnt_data), DISK_BLOCK_SIZE) + 1 + (seg->blk_size / DISK_BLOCK_SIZE * ((DIVIDE_ROUND_UP(seg->allocation, BLKS_PER_LMAP - 1)) + seg->allocation)); if ((uint4)avail_blocks < blocks_for_create) { gtm_putmsg(VARLSTCNT(6) ERR_NOSPACECRE, 4, LEN_AND_STR(path), blocks_for_create, (uint4)avail_blocks); send_msg(VARLSTCNT(6) ERR_NOSPACECRE, 4, LEN_AND_STR(path), blocks_for_create, (uint4)avail_blocks); CLEANUP(EXIT_ERR); return EXIT_ERR; } blocks_for_extension = (seg->blk_size / DISK_BLOCK_SIZE * ((DIVIDE_ROUND_UP(EXTEND_WARNING_FACTOR * seg->ext_blk_count, BLKS_PER_LMAP - 1)) + EXTEND_WARNING_FACTOR * seg->ext_blk_count)); if ((uint4)(avail_blocks - blocks_for_create) < blocks_for_extension) { gtm_putmsg(VARLSTCNT(8) ERR_LOWSPACECRE, 6, LEN_AND_STR(path), EXTEND_WARNING_FACTOR, blocks_for_extension, DISK_BLOCK_SIZE, (uint4)(avail_blocks - blocks_for_create)); send_msg(VARLSTCNT(8) ERR_LOWSPACECRE, 6, LEN_AND_STR(path), EXTEND_WARNING_FACTOR, blocks_for_extension, DISK_BLOCK_SIZE, (uint4)(avail_blocks - blocks_for_create)); } } gv_cur_region->dyn.addr->file_cntl = &fc; fc.file_info = (void*)&udi_struct; udi->fd = fd; cs_data = (sgmnt_data_ptr_t)malloc(sizeof(sgmnt_data)); memset(cs_data, 0, sizeof(*cs_data)); cs_data->createinprogress = TRUE; cs_data->semid = INVALID_SEMID; cs_data->shmid = INVALID_SHMID; /* We want our datablocks to start on what would be a block boundary within the file so pad the fileheader if necessary to make this happen. */ padded_len = ROUND_UP(sizeof(sgmnt_data), BLK_SIZE); padded_vbn = DIVIDE_ROUND_UP(padded_len, DISK_BLOCK_SIZE) + 1; norm_vbn = DIVIDE_ROUND_UP(sizeof(sgmnt_data), DISK_BLOCK_SIZE) + 1; cs_data->start_vbn = padded_vbn; cs_data->free_space += (padded_vbn - norm_vbn) * DISK_BLOCK_SIZE; cs_data->acc_meth = gv_cur_region->dyn.addr->acc_meth; if (udi->raw) { /* calculate total blocks, reduce to make room for the * database header (size rounded up to a block), then * make into a multiple of BLKS_PER_LMAP to have a complete bitmap * for each set of blocks. */ cs_data->trans_hist.total_blks = raw_dev_size - ROUND_UP(sizeof(sgmnt_data), DISK_BLOCK_SIZE); cs_data->trans_hist.total_blks /= (uint4)(((gd_segment *)gv_cur_region->dyn.addr)->blk_size); if (0 == (cs_data->trans_hist.total_blks - DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, BLKS_PER_LMAP - 1) % (BLKS_PER_LMAP - 1))) cs_data->trans_hist.total_blks -= 1; /* don't create a bitmap with no data blocks */ cs_data->extension_size = 0; PRINTF("Raw device size is %dK, %d GDS blocks\n", raw_dev_size / 1000, cs_data->trans_hist.total_blks); } else { cs_data->trans_hist.total_blks = gv_cur_region->dyn.addr->allocation; /* There are (bplmap - 1) non-bitmap blocks per bitmap, so add (bplmap - 2) to number of non-bitmap blocks * and divide by (bplmap - 1) to get total number of bitmaps for expanded database. (must round up in this * manner as every non-bitmap block must have an associated bitmap) */ cs_data->trans_hist.total_blks += DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, BLKS_PER_LMAP - 1); cs_data->extension_size = gv_cur_region->dyn.addr->ext_blk_count; } mucregini(cs_data->trans_hist.total_blks); cs_data->createinprogress = FALSE; LSEEKWRITE(udi->fd, 0, cs_data, sizeof(sgmnt_data), status); if (0 != status) { SPRINTF_AND_PERROR("Error writing out header for file %s\n"); CLEANUP(EXIT_ERR); return EXIT_ERR; } cc = (char*)malloc(DISK_BLOCK_SIZE); memset(cc, 0, DISK_BLOCK_SIZE); LSEEKWRITE(udi->fd, (cs_data->start_vbn - 1) * DISK_BLOCK_SIZE + ((off_t)(cs_data->trans_hist.total_blks) * cs_data->blk_size), cc, DISK_BLOCK_SIZE, status); if (0 != status) { SPRINTF_AND_PERROR("Error writing out end of file %s\n"); CLEANUP(EXIT_ERR); return EXIT_ERR; } if ((!udi->raw) && (-1 == CHMOD(pblk.l_dir, 0666))) { SPRINTF_AND_PERROR("Error changing file mode on file %s\n"); CLEANUP(EXIT_WRN); return EXIT_WRN; } CLEANUP(EXIT_NRM); PRINTF("Created file %s\n", path); return EXIT_NRM; }