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. */
matches_version(char * min_version)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
go(char * libc,char * min_version)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 //---------------------------------------------------------------------------
main(int argc,char ** argv)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