cScm Configuration Daemon

cScm – is a tool to convert SCM configuration files into binary format and store its in shared memory for reading by cSvn-ui and cGit-ui CGI scripts

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