Allow exact-match excludes in PATHMAPNOT
authorRalph Ronnquist <rrq@rrq.au>
Wed, 27 Aug 2025 10:25:00 +0000 (20:25 +1000)
committerRalph Ronnquist <rrq@rrq.au>
Wed, 27 Aug 2025 10:25:00 +0000 (20:25 +1000)
libpathmap-0.c
libtarmap-0.c

index b327bb98f517ccfc936ff41baecee986dbca0c52..f7dea491de8c065aa82f0117e05624645f26decc 100644 (file)
@@ -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;
index 8625616493774fecfe50ce1556c2f81d41daa3b9..385bfae0337b2781d9797f6afd4fd2680ae495b6 100644 (file)
@@ -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 );