LCOV - code coverage report
Current view: top level - app/fdctl/configure - configure.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 164 0.0 %
Date: 2024-11-13 11:58:15 Functions: 0 7 0.0 %

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

Generated by: LCOV version 1.14