From: Ralph Ronnquist Date: Wed, 27 Aug 2025 10:25:00 +0000 (+1000) Subject: Allow exact-match excludes in PATHMAPNOT X-Git-Url: https://git.rrq.selfhost.au/?a=commitdiff_plain;h=65f5db1b5f6b9716a6e3bdd7d8f9dd9275fd8af8;p=rrq%2Fpathmap.git Allow exact-match excludes in PATHMAPNOT --- diff --git a/libpathmap-0.c b/libpathmap-0.c index b327bb9..f7dea49 100644 --- a/libpathmap-0.c +++ b/libpathmap-0.c @@ -36,6 +36,7 @@ static struct { int count; int root_length; char *root; + int root_index; } prefix; // Alphabetical ordering of char* records. @@ -44,6 +45,61 @@ static int alphorder(const void *a, const void *b) { return x; } +// Binary search for a given path prefix. +static int binsearch(const char *path) { + int lo = 0; + int hi = prefix.count; + while ( lo < hi ) { + int m = ( lo + hi ) / 2; + int x = strcmp( path, prefix.data[ m ] ); + if ( x == 0 ) { + return m; + } + if ( x < 0 ) { + hi = m; + } else { + lo = m + 1; + } + } + return - lo - 1; +} + +// Use binary search for a given path prefix, and for mismatch check +// if entry prior to insertion is a path prefix. Returns the index of +// longest path prefix match or (-i-1)<0 for mismatch (indicating +// insertion point i) +static int prefixsearch(const char *path) { + int lo = binsearch( path ); +#if 0 + if ( lo >= 0 ) { + fprintf( stderr, "libpathmap: [%d] %s\n", lo, prefix.data[ lo ] ); + } else { + fprintf( stderr, "libpathmap: [%d] ... \n", lo ); + } +#endif + if ( lo >= -1 ) { + return lo; + } + int p = - lo - 2; + // p = before insertion point for mismatch; check if it's prefix + int n = strlen( prefix.data[ p ] ); + if ( ( strncmp( prefix.data[ p ], path, n ) != 0 ) ) { + return lo; // Not a prefix + } + if ( *(path+n) == '/' ) { + //fprintf( stderr, "libpathmap: exclude prefix %s\n", + // prefix.data[ p ] ); + return p; // matching prefix at p + } + // The root path must be prefix; any exclude path may match in full + if ( ( p != prefix.root_index ) && *(path+n) == 0 ) { + //fprintf( stderr, "libpathmap: exclude match %s\n", + // prefix.data[ p ] ); + return p; + } + return lo; +} + // Utility function to load the prefixes. static void load_prefixes() { char *data = getenv( PATHMAPNOT ); @@ -75,34 +131,7 @@ static void load_prefixes() { prefix.root = prefix.data[ 0 ]; prefix.root_length = strlen( prefix.root ); qsort( prefix.data, n, sizeof( char* ), alphorder ); -} - -// Binary search for a given path prefix. Returns the index of longest -// prefix match or (-i-1)<0 for mismatch (indicating insertion point i) -static int binsearch(const char *path) { - int lo = 0; - int hi = prefix.count; - while ( lo < hi ) { - int m = ( lo + hi ) / 2; - int x = strcmp( path, prefix.data[ m ] ); - if ( x == 0 ) { - return m; - } - if ( x < 0 ) { - hi = m; - } else { - lo = m + 1; - } - } - // lo = insertion point for mismatch; check if lo-1 is prefix - if ( lo > 0 ) { - int n = strlen( prefix.data[ lo - 1 ] ); - if ( ( strncmp( prefix.data[ lo - 1 ], path, n ) == 0 ) && - ( *(path+n) == '/' ) ) { - return lo - 1; - } - } - return - lo - 1; + prefix.root_index = binsearch( prefix.root ); } // Utility function to lookup a matching prefix for the given path. If @@ -111,16 +140,18 @@ static int binsearch(const char *path) { // by the given path. Note that prefixing only applies to absolute // paths. static char *maybe_add_prefix(const char *path) { - fprintf( stderr, "libpathmap: check %s\n", path ); if ( prefix.count > 0 && *path == '/' ) { - int x = binsearch( path ); + //fprintf( stderr, "libpathmap: check %s\n", path ); + int x = prefixsearch( path ); //fprintf( stderr, "libpathmap: %d %s\n", x, path ); if ( x < 0 ) { char *p = (char*)malloc( strlen( path ) + prefix.root_length + 1 ); memcpy( p, prefix.root, prefix.root_length ); strcpy( p + prefix.root_length, path ); - fprintf( stderr, "libpathmap: => %s\n", p ); + //fprintf( stderr, "libpathmap: [%s] %s\n", prefix.root, path ); return p; + } else { + //fprintf( stderr, "libpathmap: [] %s\n", path ); } } return 0; diff --git a/libtarmap-0.c b/libtarmap-0.c index 8625616..385bfae 100644 --- a/libtarmap-0.c +++ b/libtarmap-0.c @@ -135,9 +135,9 @@ void so_init() { } //fprintf( stderr, "libtarmap: %s\n", tarfile? tarfile : "(null)" ); libc6 = dlopen( "libc.so.6", RTLD_LAZY ); - real_openat = dlsym( libc6, "openat" ); - real_open = dlsym( libc6, "open" ); - real_fopen = dlsym( libc6, "fopen" ); + //real_openat = dlsym( libc6, "openat" ); + //real_open = dlsym( libc6, "open" ); + //real_fopen = dlsym( libc6, "fopen" ); if ( ( data.tarmap = realpath( tarfile, 0 ) ) == 0 ) { // Cannot find the tar file .. that's total badness! perror( tarfile );