• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) International Business Machines  Corp., 2003
3  *    AUTHOR: Paul Larson <plars@linuxtestproject.org>
4  * Copyright (c) 2016 Cyril Hrubis <chrubis@suse.cz>
5  *
6  * This program is free software;  you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14  * the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program;  if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <limits.h>
25 #include <sys/utsname.h>
26 #include "test.h"
27 
parse_digit(const char * str,int * d)28 static char *parse_digit(const char *str, int *d)
29 {
30 	unsigned long v;
31 	char *end;
32 
33 	v = strtoul(str, &end, 10);
34 	if (str == end)
35 		return NULL;
36 
37 	if (v > INT_MAX)
38 		return NULL;
39 
40 	*d = v;
41 
42 	if (*end != '.')
43 		return NULL;
44 
45 	return end + 1;
46 }
47 
tst_parse_kver(const char * str_kver,int * v1,int * v2,int * v3)48 void tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
49 {
50 	const char *str = str_kver;
51 
52 	*v1 = 0;
53 	*v2 = 0;
54 	*v3 = 0;
55 
56 	if (!(str = parse_digit(str, v1)))
57 		goto err;
58 
59 	if (!(str = parse_digit(str, v2)))
60 		goto err;
61 
62 	/*
63 	 * We ignore all errors here in order not to fail with versions as
64 	 * "2.4" or "2.6.18".
65 	 */
66 	parse_digit(str, v3);
67 
68 	return;
69 err:
70 	tst_resm(TWARN,
71 		 "Invalid kernel version %s, expected %%d.%%d.%%d", str_kver);
72 }
73 
tst_kvercmp(int r1,int r2,int r3)74 int tst_kvercmp(int r1, int r2, int r3)
75 {
76 	int a1, a2, a3;
77 	int testver, currver;
78 	struct utsname uval;
79 
80 	uname(&uval);
81 	tst_parse_kver(uval.release, &a1, &a2, &a3);
82 
83 	testver = (r1 << 16) + (r2 << 8) + r3;
84 	currver = (a1 << 16) + (a2 << 8) + a3;
85 
86 	return currver - testver;
87 }
88 
tst_kexvcmp(char * tst_exv,char * cur_ver)89 static int tst_kexvcmp(char *tst_exv, char *cur_ver)
90 {
91 	int c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0;
92 	int t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0;
93 	int ret;
94 
95 	sscanf(cur_ver, "%d.%d.%d-%d.%d", &c1, &c2, &c3, &c4, &c5);
96 	sscanf(tst_exv, "%d.%d.%d-%d.%d", &t1, &t2, &t3, &t4, &t5);
97 
98 	if ((ret = c1 - t1))
99 		return ret;
100 	if ((ret = c2 - t2))
101 		return ret;
102 	if ((ret = c3 - t3))
103 		return ret;
104 	if ((ret = c4 - t4))
105 		return ret;
106 
107 	return c5 - t5;
108 }
109 
tst_kvercmp2(int r1,int r2,int r3,struct tst_kern_exv * vers)110 int tst_kvercmp2(int r1, int r2, int r3, struct tst_kern_exv *vers)
111 {
112 	int i;
113 	struct utsname uval;
114 	char *kver;
115 	const char *cur_dist_name = NULL;
116 
117 	uname(&uval);
118 	kver = uval.release;
119 	if (strstr(kver, ".el5uek")) {
120 		cur_dist_name = "OL5UEK";
121 	} else if (strstr(kver, ".el5")) {
122 		cur_dist_name = "RHEL5";
123 	} else if (strstr(kver, ".el6uek")) {
124 		cur_dist_name = "OL6UEK";
125 	} else if (strstr(kver, ".el6")) {
126 		cur_dist_name = "RHEL6";
127 	}
128 
129 	if (cur_dist_name == NULL)
130 		return tst_kvercmp(r1, r2, r3);
131 
132 	for (i = 0; vers[i].dist_name; i++) {
133 		if (!strcmp(vers[i].dist_name, cur_dist_name)) {
134 			tst_resm(TINFO, "Detected %s using kernel version %s",
135 				 cur_dist_name, kver);
136 			return tst_kexvcmp(vers[i].extra_ver, kver);
137 		}
138 	}
139 
140 	return tst_kvercmp(r1, r2, r3);
141 }
142