#ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include /* chmod(2) */ #include #include #include #include #include /* strdup(3) */ #include /* basename(3) */ #include /* tolower(3) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern const char *SHM_BCF; FILE *bcf = NULL; char *bcf_fname = NULL; static void *bcf_shm_address = NULL; static int bcf_shm_fd = -1; static int snum, rnum, dnum, global_dnum, global_rnum, indent; static unsigned char *ftab, *stab = NULL; static Bcf32_Off stabsz = 0; static Bcf32_Off shoff; /* section header table’s file offset in bytes */ static Bcf32_Off rhoff; /* repository header table’s file offset in bytes */ static Bcf32_Off dtoff; /* data entries table’s file offset in bytes */ static Bcf32_Off stoff; /* string table’s file offset in bytes */ static Bcf32_fhdr *fhdr; static Bcf32_shdr *shdr; static Bcf32_rhdr *rhdr; static Bcf32_dntr *dntr; void bcf_shm_free( void ) { if( bcf_shm_address ) { struct stat st; if( !fstat( bcf_shm_fd, (struct stat *)&st ) ) { (void)munmap( bcf_shm_address, (size_t)st.st_size ); bcf_shm_address = NULL; bcf_shm_fd = shm_unlink( SHM_BCF ); } } bcf_shm_address = NULL; bcf_shm_fd = -1; } /************************************************ Функции создания BCF файла по таблице symlist: */ static Bcf32_Off extend_strtab( const char *val ) { Bcf32_Off off = 1; Bcf32_Off len = 0; unsigned char *dest = NULL; if( !stab ) { /************************************* The first string in strtab is equal to "" for empty strings. */ stabsz = (Bcf32_Off)(strlen( val ) + 2); stab = (unsigned char *)xmalloc( (size_t)stabsz ); (void)strncpy( (char *)&stab[1], val, stabsz - 1 ); return off; } else { off = stabsz; len = (Bcf32_Off)(strlen( val ) + 1); stabsz += len; stab = (unsigned char *)xrealloc( (void *)stab, (size_t)stabsz ); dest = &stab[off]; (void)strncpy( (char *)dest, val, len ); return off; } } static void count_symbols( int *snum, int *rnum, int *dnum, int *gdts, int *grps, SYMBOL *list ) { SYMBOL *head = list; if( !head ) return; while( head ) { /************************************ count symbols( head ): */ switch( head->type ) { case STRING: if( indent == 0 ) *gdts += 1; *dnum += 1; break; case PATH: if( indent == 0 ) *gdts += 1; *dnum += 1; break; case NUMERICAL: if( indent == 0 ) *gdts += 1; *dnum += 1; break; case SECTION: *snum += 1; break; case REPO: if( indent == 0 ) *grps += 1; *rnum += 1; break; default: break; } if( head->list ) { indent += 1; count_symbols( snum, rnum, dnum, gdts, grps, head->list ); } /* End of count symbols( head ). ************************************/ head = head->next; } } static void write_global_data( SYMBOL *list ) { SYMBOL *head = list; if( !head ) return; while( head ) { /************************************ global symbols( head ): */ switch( head->type ) { case STRING: dntr->d_name = extend_strtab( (const char *)head->name ); dntr->d_type = DT_STRING; dntr->_v.d_valptr = extend_strtab( (const char *)head->u.string ); dtoff += (Bcf32_Off)sizeof( Bcf32_dntr ); ++dntr; break; case PATH: dntr->d_name = extend_strtab( (const char *)head->name ); dntr->d_type = DT_PATH; dntr->_v.d_valptr = extend_strtab( (const char *)head->u.path ); dtoff += (Bcf32_Off)sizeof( Bcf32_dntr ); ++dntr; break; case NUMERICAL: dntr->d_name = extend_strtab( (const char *)head->name ); dntr->d_type = DT_NUMERICAL; dntr->_v.d_value = head->u.value; dtoff += (Bcf32_Off)sizeof( Bcf32_dntr ); ++dntr; break; default: break; } /* End of global symbols( head ). ************************************/ head = head->next; } } static Bcf32_Half write_repo_data( SYMBOL *list ) { Bcf32_Half cntr = 0; SYMBOL *head = list; if( !head ) return cntr; while( head ) { /************************************ symbols( head ): */ switch( head->type ) { case STRING: dntr->d_name = extend_strtab( (const char *)head->name ); dntr->d_type = DT_STRING; dntr->_v.d_valptr = extend_strtab( (const char *)head->u.string ); dtoff += (Bcf32_Off)sizeof( Bcf32_dntr ); ++dntr; ++cntr; break; case PATH: dntr->d_name = extend_strtab( (const char *)head->name ); dntr->d_type = DT_PATH; dntr->_v.d_valptr = extend_strtab( (const char *)head->u.path ); dtoff += (Bcf32_Off)sizeof( Bcf32_dntr ); ++dntr; ++cntr; break; case NUMERICAL: dntr->d_name = extend_strtab( (const char *)head->name ); dntr->d_type = DT_NUMERICAL; dntr->_v.d_value = head->u.value; dtoff += (Bcf32_Off)sizeof( Bcf32_dntr ); ++dntr; ++cntr; break; default: break; } /* End of symbols( head ). ************************************/ head = head->next; } return cntr; } static void write_global_repos( SYMBOL *list ) { SYMBOL *head = list; if( !head ) return; while( head ) { /************************************ global symbols( head ): */ if( head->type == REPO ) { rhdr->r_rhdr = extend_strtab( (const char *)head->u.path ); rhdr->r_rdata = dtoff; rhdr->r_dnum = write_repo_data( head->list ); rhoff += (Bcf32_Off)sizeof( Bcf32_rhdr ); ++rhdr; } /* End of global symbols( head ). ************************************/ head = head->next; } } static Bcf32_Half write_repos( SYMBOL *list ) { Bcf32_Half cntr = 0; SYMBOL *head = list; if( !head ) return cntr; while( head ) { /************************************ symbols( head ): */ if( head->type == REPO ) { rhdr->r_rhdr = extend_strtab( (const char *)head->u.path ); rhdr->r_rdata = dtoff; rhdr->r_dnum = write_repo_data( head->list ); rhoff += (Bcf32_Off)sizeof( Bcf32_rhdr ); ++rhdr; ++cntr; } /* End of symbols( head ). ************************************/ head = head->next; } return cntr; } static void write_sections( SYMBOL *list ) { SYMBOL *head = list; if( !head ) return; while( head ) { /************************************ global symbols( head ): */ if( head->type == SECTION ) { (void)strncpy( (char *)shdr->s_name, SMAG_REPOS, (size_t)SI_NIDENT ); shdr->s_type = ST_REPOS; shdr->s_shdr = extend_strtab( (const char *)head->u.string ); shdr->s_sdata = rhoff; shdr->s_dnum = write_repos( head->list );; shoff += (Bcf32_Off)sizeof( Bcf32_shdr ); ++shdr; } /* End of global symbols( head ). ************************************/ head = head->next; } } int write_binary_config( void ) { int ret = 0; ftab = NULL; stab = NULL; snum = 0, rnum = 0, dnum = 0, global_dnum = 0, global_rnum = 0, indent = 0, stabsz = 0; fhdr = NULL, shdr = NULL, rhdr = NULL, dntr = NULL; shoff = 0, rhoff = 0, dtoff = 0, stoff = 0; count_symbols( &snum, &rnum, &dnum, &global_dnum, &global_rnum, symlist ); if( global_dnum ) snum += 1; /* add .global section for global variables */ if( global_rnum ) snum += 1; /* add noname .repos section for global repositories */ shoff = (Bcf32_Off)sizeof( Bcf32_fhdr ); rhoff = (Bcf32_Off)(shoff + snum * sizeof( Bcf32_shdr )); dtoff = (Bcf32_Off)(rhoff + rnum * sizeof( Bcf32_rhdr )); stoff = (Bcf32_Off)(dtoff + dnum * sizeof( Bcf32_dntr )); ftab = (unsigned char *)xmalloc( (size_t)stoff ); /****************** Fill File Header */ fhdr = (Bcf32_fhdr *)ftab; (void)strncpy( (char *)fhdr->b_ident, BCFMAG, (size_t)SZBCFMAG ); fhdr->b_ident[BI_CLASS] = BCF_CLASS_32; #if __BYTE_ORDER == __LITTLE_ENDIAN fhdr->b_ident[BI_DATA] = BCF_DATA_LSB; #else fhdr->b_ident[BI_DATA] = BCF_DATA_MSB; #endif fhdr->b_ident[BI_VERSION] = BV_CURRENT; fhdr->b_ident[BI_PAD] = BCF_PAD; fhdr->b_hsize = (Bcf32_Half)sizeof( Bcf32_fhdr ); fhdr->b_shoff = (Bcf32_Off)shoff; fhdr->b_shentsize = (Bcf32_Half)sizeof( Bcf32_shdr ); fhdr->b_shnum = (Bcf32_Half)snum; fhdr->b_rhoff = (Bcf32_Off)rhoff; fhdr->b_rhentsize = (Bcf32_Half)sizeof( Bcf32_rhdr ); fhdr->b_rhnum = (Bcf32_Half)rnum; fhdr->b_dtoff = (Bcf32_Off)dtoff; fhdr->b_dtentsize = (Bcf32_Half)sizeof( Bcf32_dntr ); fhdr->b_dtnum = (Bcf32_Half)dnum; fhdr->b_stoff = (Bcf32_Off)stoff; shdr = (Bcf32_shdr *)&ftab[shoff]; rhdr = (Bcf32_rhdr *)&ftab[rhoff]; dntr = (Bcf32_dntr *)&ftab[dtoff]; if( global_dnum ) { (void)strncpy( (char *)shdr->s_name, SMAG_GLOBAL, (size_t)SI_NIDENT ); shdr->s_type = ST_GLOBAL; shdr->s_shdr = 0; /* Global section is always a first noname .global section */ shdr->s_sdata = fhdr->b_dtoff; shdr->s_dnum = (Bcf32_Half)global_dnum; write_global_data( symlist ); shoff += (Bcf32_Off)sizeof( Bcf32_shdr ); ++shdr; } if( global_rnum ) { (void)strncpy( (char *)shdr->s_name, SMAG_REPOS, (size_t)SI_NIDENT ); shdr->s_type = ST_REPOS; shdr->s_shdr = 0; /* Global repos plased in the second noname .repos section */ shdr->s_sdata = fhdr->b_rhoff; shdr->s_dnum = (Bcf32_Half)global_rnum; write_global_repos( symlist ); shoff += (Bcf32_Off)sizeof( Bcf32_shdr ); ++shdr; } write_sections( symlist ); /********************** Whole BCF file size: */ fhdr->b_fsize = (Bcf32_Word)( stoff + stabsz ); bcf_shm_free(); bcf_shm_fd = shm_open( SHM_BCF, O_CREAT | O_TRUNC | O_RDWR, 0644 ); if( bcf_shm_fd != -1 ) { (void)ftruncate( bcf_shm_fd, (size_t)fhdr->b_fsize ); bcf_shm_address = mmap( NULL, (size_t)fhdr->b_fsize, PROT_WRITE, MAP_SHARED, bcf_shm_fd, 0 ); if( bcf_shm_address != MAP_FAILED ) { memcpy( bcf_shm_address, (const void *)ftab, (size_t)stoff ); memcpy( bcf_shm_address + (size_t)stoff, (const void *)stab, (size_t)stabsz ); } } if( bcf_fname ) { bcf = fopen( (const char *)bcf_fname, "w" ); if( !bcf ) { FATAL_ERROR( "Cannot open BCF file: %s", bcf_fname ); } } (void)fwrite( (void *)ftab, (size_t)stoff, 1, bcf ); (void)fwrite( (void *)stab, (size_t)stabsz, 1, bcf ); if( bcf_fname ) { if( bcf ) { fclose( bcf ); bcf = NULL; } /* Do not free bcf_fname[] */ } if( ftab ) { free( ftab ); ftab = NULL; } if( stab ) { free( stab ); stab = NULL; } shoff = 0, rhoff = 0, dtoff = 0, stoff = 0; fhdr = NULL, shdr = NULL, rhdr = NULL, dntr = NULL; snum = 0, rnum = 0, dnum = 0, global_dnum = 0, global_rnum = 0, indent = 0, stabsz = 0; ret = 1; /* success */ return ret; }