diff options
Diffstat (limited to 'cscmd/bconf.c')
-rw-r--r-- | cscmd/bconf.c | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/cscmd/bconf.c b/cscmd/bconf.c new file mode 100644 index 0000000..8576805 --- /dev/null +++ b/cscmd/bconf.c @@ -0,0 +1,477 @@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <sys/sysinfo.h> +#include <sys/types.h> +#include <stdint.h> +#include <dirent.h> +#include <sys/stat.h> /* chmod(2) */ +#include <sys/file.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <limits.h> +#include <string.h> /* strdup(3) */ +#include <libgen.h> /* basename(3) */ +#include <ctype.h> /* tolower(3) */ +#include <errno.h> +#include <time.h> +#include <sys/time.h> +#include <pwd.h> +#include <grp.h> +#include <stdarg.h> +#include <unistd.h> +#include <endian.h> + +#include <error.h> +#include <msglog.h> +#include <xalloc.h> +#include <symtab.h> +#include <parse.h> +#include <bconf.h> + +#include <defs.h> + +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; +} |