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-10-22 18:10:43 Functions: 0 5 0.0 %

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

Generated by: LCOV version 1.14