LCOV - code coverage report
Current view: top level - util/wksp - fd_wksp_io.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 144 0.0 %
Date: 2026-03-19 18:19:27 Functions: 0 5 0.0 %

          Line data    Source code
       1             : #include "fd_wksp_private.h"
       2             : 
       3             : #include <stdio.h>
       4             : #include <errno.h>
       5             : #include <unistd.h>
       6             : #include <fcntl.h>
       7             : 
       8             : /* fd_wksp_private_checkpt_read reads up to the leading buf_max bytes at
       9             :    path into buf.  On success, returns 0 and *_buf_sz will contain the
      10             :    number of bytes read.  Returns a fd_io_strerror compatible error code
      11             :    on failure and *_buf_sz will be unchanged (buf might have been
      12             :    clobbered). */
      13             : 
      14             : static int
      15             : fd_wksp_private_checkpt_read( char const * path,       /* Assumes valid */
      16             :                               void *       buf,        /* Assumes valid */
      17             :                               ulong        buf_max,    /* Assumes buf_max>=12 */
      18           0 :                               ulong *      _buf_sz ) { /* Assumes non-NULL */
      19             : 
      20           0 :   int fd = open( path, O_RDONLY, (mode_t)0 );
      21           0 :   if( FD_UNLIKELY( fd==-1 ) ) return errno;
      22             : 
      23           0 :   int err = fd_io_read( fd, buf, 12UL, buf_max, _buf_sz );
      24             : 
      25           0 :   if( FD_UNLIKELY( close( fd ) ) )
      26           0 :     FD_LOG_WARNING(( "close(\"%s\") failed (%i-%s); attempting to continue", path, errno, fd_io_strerror( errno ) ));
      27             : 
      28           0 :   return err;
      29           0 : }
      30             : 
      31             : int
      32             : fd_wksp_preview( char const *        path,
      33           0 :                  fd_wksp_preview_t * _opt_preview ) {
      34             : 
      35             :   /* Check input args */
      36             : 
      37           0 :   if( FD_UNLIKELY( !path ) ) return FD_WKSP_ERR_INVAL;
      38             : 
      39           0 :   fd_wksp_preview_t stack_preview[1];
      40           0 :   if( !_opt_preview ) _opt_preview = stack_preview; /* cmov */
      41             : 
      42             :   /* Read the wksp checkpt header.  165 is large enough to
      43             :      handle decoding an arbitrarily corrupted V1 header (14 worst case
      44             :      SVW encoded ulongs at 9 bytes each followed by a worst case
      45             :      non-'\0' bytes of name at 39==FD_SHMEM_NAME_MAX-1 bytes) and an
      46             :      arbitrarily corrupted V2 header (a 80 byte struct stored
      47             :      uncompressed). */
      48             : 
      49           0 :   uchar buf[ 165 ];
      50           0 :   ulong buf_sz;
      51           0 :   int   err = fd_wksp_private_checkpt_read( path, buf, 165UL, &buf_sz );
      52           0 :   if( FD_UNLIKELY( err ) ) return FD_WKSP_ERR_FAIL;
      53             : 
      54             :   /* If we read a supported valid V2 header, return the requested
      55             :      preview info */
      56             : 
      57           0 :   fd_wksp_checkpt_v2_hdr_t * v2 = (fd_wksp_checkpt_v2_hdr_t *)buf;
      58             : 
      59           0 :   ulong name_len = fd_shmem_name_len( v2->name ); /* tail reading safe */
      60             : 
      61           0 :   if( FD_LIKELY( (sizeof(fd_wksp_checkpt_v2_hdr_t)<=buf_sz                         ) &     /* header not truncated */
      62           0 :                  (v2->magic==FD_WKSP_MAGIC                                         ) &     /* with valid magic */
      63           0 :                  (v2->style==FD_WKSP_CHECKPT_STYLE_V2                              ) &     /* with valid style */
      64           0 :                  (fd_checkpt_frame_style_is_supported( v2->frame_style_compressed )) &     /* with supported compression */
      65           0 :                  (v2->reserved==0U                                                 ) &     /* with expected reserved */
      66           0 :                  (name_len>0UL                                                     ) &     /* with valid name */
      67             :                  /* ignore seed (arbitrary) */
      68           0 :                  (fd_wksp_footprint( v2->part_max, v2->data_max )>0UL              ) ) ) { /* with valid part_max / data_max */
      69           0 :     _opt_preview->style    = v2->style;
      70           0 :     _opt_preview->seed     = v2->seed;
      71           0 :     _opt_preview->part_max = v2->part_max;
      72           0 :     _opt_preview->data_max = v2->data_max;
      73           0 :     memcpy( _opt_preview->name, v2->name, name_len+1UL );
      74           0 :     return FD_WKSP_SUCCESS;
      75           0 :   }
      76             : 
      77             :   /* Otherwise, if we read a supported valid V1 header, return the
      78             :      requested preview info */
      79             : 
      80           0 :   uchar const * cur = buf;
      81             : 
      82           0 :   ulong magic;     cur = fd_ulong_svw_dec( cur, &magic     ); /* safe to tail read */
      83           0 :   ulong style_ul;  cur = fd_ulong_svw_dec( cur, &style_ul  ); /* " */
      84           0 :   ulong seed_ul;   cur = fd_ulong_svw_dec( cur, &seed_ul   ); /* " */
      85           0 :   ulong part_max;  cur = fd_ulong_svw_dec( cur, &part_max  ); /* " */
      86           0 :   ulong data_max;  cur = fd_ulong_svw_dec( cur, &data_max  ); /* " */
      87           0 :   ulong ts_ul;     cur = fd_ulong_svw_dec( cur, &ts_ul     ); /* " */
      88           0 :   ulong app_id;    cur = fd_ulong_svw_dec( cur, &app_id    ); /* " */
      89           0 :   ulong thread_id; cur = fd_ulong_svw_dec( cur, &thread_id ); /* " */
      90           0 :   ulong host_id;   cur = fd_ulong_svw_dec( cur, &host_id   ); /* " */
      91           0 :   ulong cpu_id;    cur = fd_ulong_svw_dec( cur, &cpu_id    ); /* " */
      92           0 :   ulong group_id;  cur = fd_ulong_svw_dec( cur, &group_id  ); /* " */
      93           0 :   ulong tid;       cur = fd_ulong_svw_dec( cur, &tid       ); /* " */
      94           0 :   ulong user_id;   cur = fd_ulong_svw_dec( cur, &user_id   ); /* " */
      95           0 :   /* name_len */   cur = fd_ulong_svw_dec( cur, &name_len  ); /* " */
      96             : 
      97           0 :   char  name[ FD_SHMEM_NAME_MAX ];
      98           0 :   ulong name_len_safe = fd_ulong_min( name_len, FD_SHMEM_NAME_MAX-1UL );
      99           0 :   memcpy( name, cur, name_len_safe );
     100           0 :   name[ name_len_safe ] = '\0';
     101             : 
     102           0 :   if( FD_LIKELY( (((ulong)(cur-buf))<=buf_sz                            ) &     /* header not truncated */
     103           0 :                  (magic   ==FD_WKSP_MAGIC                               ) &     /* with valid magic */
     104           0 :                  (style_ul==(ulong)FD_WKSP_CHECKPT_STYLE_V1             ) &     /* with valid style */
     105           0 :                  (seed_ul ==(ulong)(uint)seed_ul                        ) &     /* with valid seed */
     106           0 :                  (fd_wksp_footprint( part_max, data_max )>0UL           ) &     /* with valid part_max / data_max */
     107             :                  /* ignore ts_ul     (metadata) */
     108             :                  /* ignore app_id    (metadata) */
     109             :                  /* ignore thread_id (metadata) */
     110             :                  /* ignore host_id   (metadata) */
     111             :                  /* ignore cpu_id    (metadata) */
     112             :                  /* ignore group_id  (metadata) */
     113             :                  /* ignore tid_id    (metadata) */
     114             :                  /* ignore user_id   (metadata) */
     115           0 :                  ((name_len>0UL) & (fd_shmem_name_len( name )==name_len)) ) ) { /* with valid name */
     116           0 :     _opt_preview->style    = (int)style_ul;
     117           0 :     _opt_preview->seed     = (uint)seed_ul;
     118           0 :     _opt_preview->part_max = part_max;
     119           0 :     _opt_preview->data_max = data_max;
     120           0 :     memcpy( _opt_preview->name, name, name_len+1UL );
     121           0 :     return FD_WKSP_SUCCESS;
     122           0 :   }
     123             : 
     124             :   /* Otherwise, this is not a supported valid wksp checkpt header */
     125             : 
     126           0 :   return FD_WKSP_ERR_CORRUPT;
     127           0 : }
     128             : 
     129             : int
     130             : fd_wksp_checkpt_tpool( fd_tpool_t * tpool,
     131             :                        ulong        t0,
     132             :                        ulong        t1,
     133             :                        fd_wksp_t *  wksp,
     134             :                        char const * path,
     135             :                        ulong        mode,
     136             :                        int          style,
     137           0 :                        char const * uinfo ) { /* TODO: CONSIDER ALLOWING SUBSET OF TAGS */
     138             : 
     139             :   /* Check input args */
     140             : 
     141           0 :   if( FD_UNLIKELY( !wksp ) ) {
     142           0 :     FD_LOG_WARNING(( "NULL wksp" ));
     143           0 :     return FD_WKSP_ERR_INVAL;
     144           0 :   }
     145             : 
     146           0 :   if( FD_UNLIKELY( !path ) ) {
     147           0 :     FD_LOG_WARNING(( "NULL path" ));
     148           0 :     return FD_WKSP_ERR_INVAL;
     149           0 :   }
     150             : 
     151           0 :   if( FD_UNLIKELY( mode!=(ulong)(mode_t)mode ) ) {
     152           0 :     FD_LOG_WARNING(( "bad mode" ));
     153           0 :     return FD_WKSP_ERR_INVAL;
     154           0 :   }
     155             : 
     156           0 :   style = fd_int_if( !!style, style, FD_HAS_LZ4 ? FD_WKSP_CHECKPT_STYLE_V3 : FD_WKSP_CHECKPT_STYLE_V2 );
     157             : 
     158           0 :   if( FD_UNLIKELY( !uinfo ) ) uinfo = "";
     159             : 
     160           0 :   char const * binfo = fd_log_build_info;
     161           0 :   if( FD_UNLIKELY( !binfo ) ) binfo = "";
     162             : 
     163             :   /* Checkpt with the appropriate style */
     164             : 
     165           0 :   switch( style ) {
     166           0 :   case FD_WKSP_CHECKPT_STYLE_V1: return fd_wksp_private_checkpt_v1( tpool, t0, t1, wksp, path, mode, uinfo );
     167           0 :   case FD_WKSP_CHECKPT_STYLE_V2: return fd_wksp_private_checkpt_v2( tpool, t0, t1, wksp, path, mode, uinfo,
     168           0 :                                                                     FD_CHECKPT_FRAME_STYLE_RAW );
     169           0 :   case FD_WKSP_CHECKPT_STYLE_V3: return fd_wksp_private_checkpt_v2( tpool, t0, t1, wksp, path, mode, uinfo,
     170           0 :                                                                     FD_CHECKPT_FRAME_STYLE_LZ4 );
     171           0 :   break;
     172           0 :   }
     173             : 
     174           0 :   FD_LOG_WARNING(( "unsupported style" ));
     175           0 :   return FD_WKSP_ERR_INVAL;
     176           0 : }
     177             : 
     178             : int
     179             : fd_wksp_restore_tpool( fd_tpool_t * tpool,
     180             :                        ulong        t0,
     181             :                        ulong        t1,
     182             :                        fd_wksp_t *  wksp,
     183             :                        char const * path,
     184           0 :                        uint         new_seed ) {
     185             : 
     186             :   /* Check input args */
     187             : 
     188           0 :   if( FD_UNLIKELY( !wksp ) ) {
     189           0 :     FD_LOG_WARNING(( "NULL wksp" ));
     190           0 :     return FD_WKSP_ERR_INVAL;
     191           0 :   }
     192             : 
     193           0 :   if( FD_UNLIKELY( !path ) ) {
     194           0 :     FD_LOG_WARNING(( "NULL path" ));
     195           0 :     return FD_WKSP_ERR_INVAL;
     196           0 :   }
     197             : 
     198             :   /* new_seed arbitrary */
     199             : 
     200             :   /* Determine which version to use */
     201             : 
     202           0 :   fd_wksp_preview_t preview[1];
     203           0 :   int err = fd_wksp_preview( path, preview );
     204           0 :   if( FD_UNLIKELY( err ) ) {
     205           0 :     FD_LOG_WARNING(( "\"%s\" does not appear to be a supported wksp checkpt", path ));
     206           0 :     return err;
     207           0 :   }
     208             : 
     209             :   /* Restore with the appropriate version */
     210             : 
     211           0 :   switch( preview->style ) {
     212           0 :   case FD_WKSP_CHECKPT_STYLE_V1: return fd_wksp_private_restore_v1( tpool, t0, t1, wksp, path, new_seed );
     213           0 :   case FD_WKSP_CHECKPT_STYLE_V2: return fd_wksp_private_restore_v2( tpool, t0, t1, wksp, path, new_seed );
     214             :   /* note: v3 is really v2 with compressed frames */
     215           0 :   default: break; /* never get here (preview already checked) */
     216           0 :   }
     217             : 
     218           0 :   FD_LOG_WARNING(( "unsupported style" ));
     219           0 :   return FD_WKSP_ERR_CORRUPT;
     220           0 : }
     221             : 
     222             : int
     223             : fd_wksp_printf( int          fd,
     224             :                 char const * path,
     225           0 :                 int          verbose ) {
     226             : 
     227           0 :   int ret = 0;
     228           0 : # define TRAP(expr) do { int _err = (expr); if( FD_UNLIKELY( _err<0 ) ) { return _err; } ret += _err; } while(0)
     229             : 
     230           0 :   if( verbose<0 ) return ret;
     231             : 
     232           0 :   TRAP( dprintf( fd, "checkpt %s (verbose %i)\n", path, verbose ) );
     233             : 
     234           0 :   fd_wksp_preview_t preview[1];
     235           0 :   int err = fd_wksp_preview( path, preview );
     236           0 :   if( FD_UNLIKELY( err ) )
     237           0 :     TRAP( dprintf( fd, "\tinvalid or unsupported (%i-%s)\n", err, fd_wksp_strerror( err ) ) );
     238           0 :   else
     239           0 :     TRAP( dprintf( fd, "\tstyle                  %-20i\n"
     240           0 :                        "\tname                   %s\n"
     241           0 :                        "\tseed                   %-20u\n"
     242           0 :                        "\tpart_max               %-20lu\n"
     243           0 :                        "\tdata_max               %-20lu\n",
     244           0 :                        preview->style, preview->name, preview->seed, preview->part_max, preview->data_max ) );
     245             : 
     246           0 :   if( verbose<1 ) return ret;
     247             : 
     248           0 :   switch( preview->style ) {
     249           0 :   case FD_WKSP_CHECKPT_STYLE_V1: TRAP( fd_wksp_private_printf_v1( fd, path, verbose ) ); break;
     250           0 :   case FD_WKSP_CHECKPT_STYLE_V2: TRAP( fd_wksp_private_printf_v2( fd, path, verbose ) ); break;
     251             :   /* note: v3 is really v2 with compressed frames */
     252           0 :   default: /* never get here (preview already checked) */
     253           0 :     TRAP( dprintf( fd, "unsupported style" ) );
     254           0 :     break;
     255           0 :   }
     256             : 
     257           0 : # undef TRAP
     258             : 
     259           0 :   return ret;
     260           0 : }

Generated by: LCOV version 1.14