// *naka* - find a file within another file
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/mman.h>
# include <ints.h>
# include <macros.h>
# include <version.h>
# include <project.h>
# include <tests.h>
# include <map.h>
# include <comp.h>
void prog_info ( FILE * out )
{
fprintf ( out , PROG_NAME " v%s - " PROG_DESCRIPTION
# ifdef DEBUG
" (debug build) "
# endif
" \n written by %s with <3 (compiled at %lu UTC (unix ts)) \n license %s. \n " ,
v_ctoss ( v_rawtoc ( PROG_VERSION ) ) ,
PROG_AUTHOUR ,
PROG_COMPILED_TIMESTAMP ,
PROG_LICENSE ) ;
}
void usage ( FILE * out , int argc , char * * argv )
{
IGNORE ( argc ) ;
prog_info ( out ) ;
fprintf ( out , " \n Usage: %s <needle> <haystack(s)...> \n " , argv [ 0 ] ? : PROG_NAME ) ;
fprintf ( out , " \n Usage: %s --help \n " , argv [ 0 ] ? : PROG_NAME ) ;
}
// err: 0 for normal exit and print to stdout.
// err: nonzero for abnormal exit and print to stderr.
noreturn void usage_then_exit ( int err , int argc , char * * argv )
{
usage ( err ? stderr : stdout , argc , argv ) ;
exit ( err ) ;
}
static int map_haystacks ( const char * const * h , map_t maps [ pOUT ] )
{
const char * path ;
while ( ( path = * h + + ) )
{
map_t * pOUT c = maps + + ;
INFO ( " Mapping haystack file `%s' (to map addr %p) " , path , c ) ;
debug_assert ( c ) ;
if ( ! map_handle_err ( map_file ( path , false , 0 , 0 , c ) ) )
//TODO: Handle unmapping previous haystacks before return
return 0 ;
}
return 1 ;
}
int main ( int argc , char * * argv )
{
TRACE ( " main start with %d (pn: %s, a1: %s) " , argc , argv [ 0 ] , argv [ 1 ] ? : " <null> " ) ;
if ( ! argv [ 1 ] )
inv_args :
usage_then_exit ( PROG_RET_ARGS , argc , argv ) ;
else if ( strcmp ( argv [ 1 ] , " --help " ) = = 0 )
usage_then_exit ( 0 , argc , argv ) ;
else if ( ! argv [ 2 ] )
goto inv_args ;
map_t needle ;
INFO ( " Mapping needle file `%s' " , argv [ 1 ] ) ;
if ( ! map_handle_err ( map_file ( argv [ 1 ] , false , 0 , 0 , & needle ) ) ) return PROG_RET_MAP_NEEDLE_FAILED ;
if ( ! map_handle_err ( map_preload ( & needle , false ) ) ) WARN ( " Failed to advise kernel about memory access: needle " ) ;
// Remove exe name from argv: now is (needle, haystacks...)
argv + = 1 ;
// Setup haystack maps
map_t haystacks [ argc - 2 ] ;
TRACE ( " Attempting to map %d haystacks " , argc - 2 ) ;
if ( ! map_haystacks ( ( const char * * ) ( argv + 1 ) , haystacks ) ) return PROG_RET_MAP_HAYSTACK_FAILED ;
//TODO: Setup thread-pool.
//TODO: Dispatch haystack maps to threadpool.
//TODO: Use either `cmp_find()` or `cmp_find_many()` to find the `needle` (mapped above) within those haystacks.
//TODO: Within the threadpool: output information regarding each match/nonmatch.
//TODO: Join the threadpool and consolidate results.
//TODO: Iterate through the haystack numbers match results, return the first non-match haystack number through `PROG_RET_MATCH_HAYSTACK_N_FAILED(n)` (haystack numbers are always nonzero). If all were matched, return 0
for ( int i = 0 ; i < ( argc - 2 ) ; i + + ) {
INFO ( " Unmapping haystack haystack file `%s' (#%d) (map addr %p) " , argv [ i + 1 ] , i + 1 , haystacks + i ) ;
if ( ! map_handle_err ( map_free ( haystacks [ i ] ) ) ) return PROG_RET_UNMAP_HAYSTACK_N_FAILED ( i + 1 ) ;
}
INFO ( " Unmapping needle file `%s' " , * argv ) ;
if ( ! map_handle_err ( map_free ( needle ) ) ) return PROG_RET_UNMAP_NEEDLE_FAILED ;
TRACE ( " main end " ) ;
return 0 ;
}