LCOV - code coverage report
Current view: top level - app/shared/commands/configure - configure.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 164 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 7 0.0 %

          Line data    Source code
       1             : #include "configure.h"
       2             : 
       3             : #include <errno.h>
       4             : #include <sys/stat.h>
       5             : 
       6             : void
       7             : configure_cmd_args( int *    pargc,
       8             :                     char *** pargv,
       9           0 :                     args_t * args) {
      10           0 :   char * usage = "usage: configure <init|check|fini> <stage>...";
      11           0 :   if( FD_UNLIKELY( *pargc < 2 ) ) FD_LOG_ERR(( "%s", usage ));
      12             : 
      13           0 :   if(      FD_LIKELY( !strcmp( *pargv[ 0 ], "check" ) ) ) args->configure.command = CONFIGURE_CMD_CHECK;
      14           0 :   else if( FD_LIKELY( !strcmp( *pargv[ 0 ], "init"  ) ) ) args->configure.command = CONFIGURE_CMD_INIT;
      15           0 :   else if( FD_LIKELY( !strcmp( *pargv[ 0 ], "fini"  ) ) ) args->configure.command = CONFIGURE_CMD_FINI;
      16           0 :   else FD_LOG_ERR(( "unrecognized command `%s`, %s", *pargv[0], usage ));
      17             : 
      18           0 :   (*pargc)--;
      19           0 :   (*pargv)++;
      20             : 
      21           0 :   for( int i=0; i<*pargc; i++ ) {
      22           0 :     if( FD_UNLIKELY( !strcmp( (*pargv)[ i ], "all" ) ) ) {
      23           0 :       (*pargc) -= i + 1;
      24           0 :       (*pargv) += i + 1;
      25           0 :       for( int j=0; j<CONFIGURE_STAGE_COUNT; j++) args->configure.stages[ j ] = STAGES[ j ];
      26           0 :       return;
      27           0 :     }
      28           0 :   }
      29             : 
      30           0 :   if( FD_UNLIKELY( *pargc >= CONFIGURE_STAGE_COUNT ) ) FD_LOG_ERR(( "too many stages specified" ));
      31             : 
      32           0 :   ulong nstage = 0;
      33           0 :   while( *pargc ) {
      34           0 :     int found = 0;
      35           0 :     for( configure_stage_t ** stage = STAGES; *stage; stage++ ) {
      36           0 :       if( FD_UNLIKELY( !strcmp( (*pargv)[0], (*stage)->name ) ) ) {
      37           0 :         args->configure.stages[ nstage++ ] = *stage;
      38           0 :         found = 1;
      39           0 :         break;
      40           0 :       }
      41           0 :     }
      42             : 
      43           0 :     if( FD_UNLIKELY( !found ) ) FD_LOG_ERR(( "unknown configure stage: %s", (*pargv)[0] ));
      44             : 
      45           0 :     (*pargc)--;
      46           0 :     (*pargv)++;
      47           0 :   }
      48           0 :   return;
      49           0 : }
      50             : 
      51             : void
      52             : configure_cmd_perm( args_t *         args,
      53             :                     fd_cap_chk_t *   chk,
      54           0 :                     config_t const * config ) {
      55           0 :   for( configure_stage_t ** stage = args->configure.stages; *stage; stage++ ) {
      56           0 :     switch( args->configure.command ) {
      57           0 :       case CONFIGURE_CMD_INIT: {
      58           0 :         int enabled = !(*stage)->enabled || (*stage)->enabled( config );
      59           0 :         if( FD_LIKELY( enabled && (*stage)->check( config ).result != CONFIGURE_OK ) )
      60           0 :           if( FD_LIKELY( (*stage)->init_perm ) ) (*stage)->init_perm( chk, config );
      61           0 :         break;
      62           0 :       }
      63           0 :       case CONFIGURE_CMD_CHECK:
      64           0 :         break;
      65           0 :       case CONFIGURE_CMD_FINI: {
      66           0 :         int enabled = !(*stage)->enabled || (*stage)->enabled( config );
      67           0 :         if( FD_LIKELY( enabled && (*stage)->check( config ).result != CONFIGURE_NOT_CONFIGURED ) )
      68           0 :           if( FD_LIKELY( (*stage)->fini_perm ) ) (*stage)->fini_perm( chk, config );
      69           0 :         break;
      70           0 :       }
      71           0 :     }
      72           0 :   }
      73           0 : }
      74             : 
      75             : int
      76             : configure_stage( configure_stage_t * stage,
      77             :                  configure_cmd_t     command,
      78           0 :                  config_t const *    config ) {
      79           0 :   if( FD_UNLIKELY( stage->enabled && !stage->enabled( config ) ) ) {
      80           0 :     FD_LOG_NOTICE(( "%s ... skipping .. not enabled", stage->name ));
      81           0 :     return 0;
      82           0 :   }
      83             : 
      84           0 :   switch( command ) {
      85           0 :     case CONFIGURE_CMD_INIT: {
      86           0 :       configure_result_t result = stage->check( config );
      87           0 :       if( FD_UNLIKELY( result.result == CONFIGURE_NOT_CONFIGURED ) )
      88           0 :         FD_LOG_NOTICE(( "%s ... unconfigured ... %s", stage->name, result.message ));
      89           0 :       else if( FD_UNLIKELY( result.result == CONFIGURE_PARTIALLY_CONFIGURED ) ) {
      90           0 :         if( FD_LIKELY( stage->fini ) ) {
      91           0 :           FD_LOG_NOTICE(( "%s ... undoing ... %s", stage->name, result.message ));
      92           0 :           stage->fini( config, 1 );
      93           0 :         } else if( FD_UNLIKELY( !stage->always_recreate ) ) {
      94           0 :           FD_LOG_ERR(( "%s ... does not support undo but was not valid ... %s", stage->name, result.message ));
      95           0 :         }
      96             : 
      97           0 :         result = stage->check( config );
      98           0 :         if( FD_UNLIKELY( result.result == CONFIGURE_PARTIALLY_CONFIGURED && !stage->always_recreate ) )
      99           0 :           FD_LOG_ERR(( "%s ... clean was unable to get back to an unconfigured state ... %s", stage->name, result.message ));
     100           0 :       } else {
     101           0 :         FD_LOG_NOTICE(( "%s ... already valid", stage->name ));
     102           0 :         return 0;
     103           0 :       }
     104             : 
     105           0 :       FD_LOG_NOTICE(( "%s ... configuring", stage->name ));
     106           0 :       if( FD_LIKELY( stage->init ) ) stage->init( config );
     107             : 
     108           0 :       result = stage->check( config );
     109           0 :       if( FD_UNLIKELY( result.result == CONFIGURE_NOT_CONFIGURED ) )
     110           0 :         FD_LOG_ERR(( "%s ... tried to initialize but didn't do anything ... %s", stage->name, result.message ));
     111           0 :       else if( FD_UNLIKELY( result.result == CONFIGURE_PARTIALLY_CONFIGURED && !stage->always_recreate ) )
     112           0 :         FD_LOG_ERR(( "%s ... tried to initialize but was still unconfigured ... %s", stage->name, result.message ));
     113           0 :       break;
     114           0 :     }
     115           0 :     case CONFIGURE_CMD_CHECK: {
     116           0 :       configure_result_t result = stage->check( config );
     117           0 :       if( FD_UNLIKELY( result.result == CONFIGURE_NOT_CONFIGURED ) ) {
     118           0 :         FD_LOG_WARNING(( "%s ... not configured ... %s", stage->name, result.message ));
     119           0 :         return 1;
     120           0 :       } else if( FD_UNLIKELY( result.result == CONFIGURE_PARTIALLY_CONFIGURED ) ) {
     121           0 :         if( FD_UNLIKELY( !stage->always_recreate ) ) {
     122           0 :           FD_LOG_WARNING(( "%s ... invalid ... %s", stage->name, result.message ));
     123           0 :           return 1;
     124           0 :         } else {
     125           0 :           FD_LOG_NOTICE(( "%s ... not configured ... must always be recreated", stage->name ));
     126           0 :         }
     127           0 :       }
     128           0 :       break;
     129           0 :     }
     130           0 :     case CONFIGURE_CMD_FINI: {
     131           0 :       configure_result_t result = stage->check( config );
     132             : 
     133           0 :       if( FD_UNLIKELY( result.result == CONFIGURE_NOT_CONFIGURED ) ) {
     134           0 :         FD_LOG_NOTICE(( "%s ... not configured ... %s", stage->name, result.message ));
     135           0 :         return 0;
     136           0 :       } else if( FD_UNLIKELY( result.result == CONFIGURE_PARTIALLY_CONFIGURED && !stage->always_recreate && !stage->fini ) ) {
     137           0 :         FD_LOG_ERR(( "%s ... not valid ... %s", stage->name, result.message ));
     138           0 :       }
     139             : 
     140           0 :       FD_LOG_NOTICE(( "%s ... finishing", stage->name ));
     141           0 :       if( FD_LIKELY( stage->fini ) ) stage->fini( config, 0 );
     142             : 
     143           0 :       result = stage->check( config );
     144           0 :       if( FD_UNLIKELY( result.result == CONFIGURE_OK && stage->init && stage->fini ) ) {
     145             :         /* if the step does nothing, it's fine if it's fully configured
     146             :             after being undone */
     147           0 :         FD_LOG_ERR(( "%s ... not undone", stage->name ));
     148           0 :       } else if( FD_UNLIKELY( result.result == CONFIGURE_PARTIALLY_CONFIGURED && !stage->always_recreate ) ) {
     149           0 :         FD_LOG_ERR(( "%s ... invalid ... %s", stage->name, result.message ));
     150           0 :       }
     151           0 :       break;
     152           0 :     }
     153           0 :   }
     154             : 
     155           0 :   return 0;
     156           0 : }
     157             : 
     158             : void
     159             : configure_cmd_fn( args_t *   args,
     160           0 :                   config_t * config ) {
     161           0 :   int error = 0;
     162             : 
     163           0 :   if( FD_LIKELY( (configure_cmd_t)args->configure.command != CONFIGURE_CMD_FINI ) ) {
     164           0 :     for( configure_stage_t ** stage = args->configure.stages; *stage; stage++ ) {
     165           0 :       if( FD_UNLIKELY( configure_stage( *stage, (configure_cmd_t)args->configure.command, config ) ) ) error = 1;
     166           0 :     }
     167           0 :   } else {
     168           0 :     ulong i;
     169           0 :     for( i=0; args->configure.stages[ i ]; i++ ) ;
     170           0 :     if( FD_LIKELY( i > 0 ) ) {
     171           0 :       for( ulong j=0; j<i; j++ ) {
     172           0 :         if( FD_UNLIKELY( configure_stage( args->configure.stages[ i-1-j ], (configure_cmd_t)args->configure.command, config ) ) ) error = 1;
     173           0 :       }
     174           0 :     }
     175           0 :   }
     176             : 
     177             : 
     178           0 :   if( FD_UNLIKELY( error ) ) FD_LOG_ERR(( "failed to configure some stages" ));
     179           0 : }
     180             : 
     181             : static configure_result_t
     182             : check_path( const char * path,
     183             :             uint         expected_uid,
     184             :             uint         expected_gid,
     185             :             uint         expected_mode,
     186           0 :             int          expected_dir ) {
     187           0 :   struct stat st;
     188           0 :   if( FD_UNLIKELY( stat( path, &st ) ) ) {
     189           0 :     if( FD_LIKELY( errno == ENOENT ) ) PARTIALLY_CONFIGURED( "path `%s` does not exist", path );
     190           0 :     PARTIALLY_CONFIGURED( "failed to stat `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) );
     191           0 :   }
     192           0 :   if( FD_UNLIKELY( expected_dir && !S_ISDIR( st.st_mode ) ) )
     193           0 :     PARTIALLY_CONFIGURED( "path `%s` is a file, not a directory", path );
     194           0 :   if( FD_UNLIKELY( !expected_dir && S_ISDIR( st.st_mode ) ) )
     195           0 :     PARTIALLY_CONFIGURED( "path `%s` is a directory, not a file", path );
     196             : 
     197           0 :   if( FD_UNLIKELY( st.st_uid != expected_uid ) )
     198           0 :     PARTIALLY_CONFIGURED( "path `%s` has uid %u, expected %u", path, st.st_uid, expected_uid );
     199           0 :   if( FD_UNLIKELY( st.st_gid != expected_gid ) )
     200           0 :     PARTIALLY_CONFIGURED( "path `%s` has gid %u, expected %u", path, st.st_gid, expected_gid );
     201           0 :   if( FD_UNLIKELY( st.st_mode != expected_mode ) )
     202           0 :     PARTIALLY_CONFIGURED( "path `%s` has mode %o, expected %o", path, st.st_mode, expected_mode );
     203             : 
     204           0 :   CONFIGURE_OK();
     205           0 : }
     206             : 
     207             : configure_result_t
     208             : check_dir( const char * path,
     209             :            uint         uid,
     210             :            uint         gid,
     211           0 :            uint         mode ) {
     212           0 :   return check_path( path, uid, gid, mode, 1 );
     213           0 : }
     214             : 
     215             : configure_result_t
     216             : check_file( const char * path,
     217             :             uint         uid,
     218             :             uint         gid,
     219           0 :             uint         mode ) {
     220           0 :   return check_path( path, uid, gid, mode, 0 );
     221           0 : }

Generated by: LCOV version 1.14