1 // Compare given libc name and version number to system name and version. 2 3 // Returns 4 // - 0 if the libc name matches is at least the minimum version (if given). 5 // - 1 if the libc name doesn't match or the version is lower than requested. 6 // - 2 if the requested libc name isn't recognised. 7 // - 3 if there was a usage error (it also prints an error message). 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #ifdef __GLIBC__ 14 #include <gnu/libc-version.h> 15 #endif 16 17 #define False 0 18 #define True 1 19 typedef int Bool; 20 21 /* Assumes the versions are x.y.z, with y and z optional. */ 22 static __attribute__((unused)) Bool matches_version(char *min_version) { 23 int a1=0, a2=0, a3=0, g1=0, g2=0, g3=0; // 'a' = actual; 'g' = given 24 const char *aversion; 25 26 if (min_version == NULL) return True; // no version specified 27 28 // get actual version number 29 #ifdef __GLIBC__ 30 aversion = gnu_get_libc_version(); 31 #else 32 aversion = "unknown"; 33 #endif 34 // We expect at least one number. 35 if (sscanf(aversion, "%d.%d.%d", &a1, &a2, &a3) < 1) return False; 36 37 // parse given version number. 38 if (sscanf(min_version, "%d.%d.%d", &g1, &g2, &g3) < 1) return False; 39 40 if (a1 > g1) return True; 41 if (a1 < g1) return False; 42 if (a2 > g2) return True; 43 if (a2 < g2) return False; 44 if (a3 >= g3) return True; 45 46 return False; 47 } 48 49 static Bool go(char* libc, char *min_version) 50 { 51 #ifdef __GLIBC__ 52 if ( 0 == strcmp( libc, "glibc" ) 53 && matches_version( min_version )) 54 return True; 55 #endif 56 57 return False; 58 } 59 60 //--------------------------------------------------------------------------- 61 // main 62 //--------------------------------------------------------------------------- 63 int main(int argc, char **argv) 64 { 65 if ( argc < 2 ) { 66 fprintf( stderr, "usage: libc_test <libc-name> [<min-version>]\n" ); 67 exit(3); // Usage error. 68 } 69 if (go( argv[1], argv[2] )) { 70 return 0; // Matched. 71 } 72 73 if ( 0 == strcmp ( argv[1], "glibc" ) ) { 74 return 1; // Requested libc name known, but this isn't it. 75 // Or it wasn't the minimum requested version. 76 } 77 return 2; // Didn't match any known libc name. 78 } 79