1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2003 3f08c3bdfSopenharmony_ci * AUTHOR: Paul Larson <plars@linuxtestproject.org> 4f08c3bdfSopenharmony_ci * Copyright (c) 2016 Cyril Hrubis <chrubis@suse.cz> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 7f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 8f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 9f08c3bdfSopenharmony_ci * (at your option) any later version. 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 12f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 17f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 18f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19f08c3bdfSopenharmony_ci */ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#include <ctype.h> 22f08c3bdfSopenharmony_ci#include <stdlib.h> 23f08c3bdfSopenharmony_ci#include <unistd.h> 24f08c3bdfSopenharmony_ci#include <string.h> 25f08c3bdfSopenharmony_ci#include <limits.h> 26f08c3bdfSopenharmony_ci#include <sys/utsname.h> 27f08c3bdfSopenharmony_ci#include "test.h" 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci#define OSRELEASE_PATH "/etc/os-release" 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_cistatic char *parse_digit(const char *str, int *d) 32f08c3bdfSopenharmony_ci{ 33f08c3bdfSopenharmony_ci unsigned long v; 34f08c3bdfSopenharmony_ci char *end; 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci v = strtoul(str, &end, 10); 37f08c3bdfSopenharmony_ci if (str == end) 38f08c3bdfSopenharmony_ci return NULL; 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci if (v > INT_MAX) 41f08c3bdfSopenharmony_ci return NULL; 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci *d = v; 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci return end; 46f08c3bdfSopenharmony_ci} 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ciint tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3) 49f08c3bdfSopenharmony_ci{ 50f08c3bdfSopenharmony_ci const char *str = str_kver; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci *v1 = 0; 53f08c3bdfSopenharmony_ci *v2 = 0; 54f08c3bdfSopenharmony_ci *v3 = 0; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci if (!(str = parse_digit(str, v1))) 57f08c3bdfSopenharmony_ci return 1; 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci if (*(str++) != '.') 60f08c3bdfSopenharmony_ci return 1; 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci if (!(str = parse_digit(str, v2))) 63f08c3bdfSopenharmony_ci return 1; 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci /* 66f08c3bdfSopenharmony_ci * Check for a short version e.g '2.4' 67f08c3bdfSopenharmony_ci */ 68f08c3bdfSopenharmony_ci if (*str == ' ' || *str == '\0' || *str == '-') 69f08c3bdfSopenharmony_ci return 0; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci if (*(str++) != '.') 72f08c3bdfSopenharmony_ci return 1; 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci /* 75f08c3bdfSopenharmony_ci * Ignore rest of the string in order not to break on versions as 76f08c3bdfSopenharmony_ci * 4.8.1-52-default. 77f08c3bdfSopenharmony_ci */ 78f08c3bdfSopenharmony_ci if (!parse_digit(str, v3)) 79f08c3bdfSopenharmony_ci return 1; 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci return 0; 82f08c3bdfSopenharmony_ci} 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ciint tst_kvcmp(const char *cur_kver, int r1, int r2, int r3) 85f08c3bdfSopenharmony_ci{ 86f08c3bdfSopenharmony_ci int a1, a2, a3; 87f08c3bdfSopenharmony_ci int testver, currver; 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci if (tst_parse_kver(cur_kver, &a1, &a2, &a3)) { 90f08c3bdfSopenharmony_ci tst_resm(TWARN, 91f08c3bdfSopenharmony_ci "Invalid kernel version %s, expected %%d.%%d.%%d", 92f08c3bdfSopenharmony_ci cur_kver); 93f08c3bdfSopenharmony_ci } 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci testver = (r1 << 16) + (r2 << 8) + r3; 96f08c3bdfSopenharmony_ci currver = (a1 << 16) + (a2 << 8) + a3; 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci return currver - testver; 99f08c3bdfSopenharmony_ci} 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ciint tst_kvercmp(int r1, int r2, int r3) 102f08c3bdfSopenharmony_ci{ 103f08c3bdfSopenharmony_ci struct utsname uval; 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci uname(&uval); 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci return tst_kvcmp(uval.release, r1, r2, r3); 108f08c3bdfSopenharmony_ci} 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ciint tst_kvexcmp(const char *tst_exv, const char *cur_ver) 111f08c3bdfSopenharmony_ci{ 112f08c3bdfSopenharmony_ci int c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0; 113f08c3bdfSopenharmony_ci int t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0; 114f08c3bdfSopenharmony_ci int ret; 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci sscanf(cur_ver, "%d.%d.%d-%d.%d", &c1, &c2, &c3, &c4, &c5); 117f08c3bdfSopenharmony_ci sscanf(tst_exv, "%d.%d.%d-%d.%d", &t1, &t2, &t3, &t4, &t5); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci if ((ret = c1 - t1)) 120f08c3bdfSopenharmony_ci return ret; 121f08c3bdfSopenharmony_ci if ((ret = c2 - t2)) 122f08c3bdfSopenharmony_ci return ret; 123f08c3bdfSopenharmony_ci if ((ret = c3 - t3)) 124f08c3bdfSopenharmony_ci return ret; 125f08c3bdfSopenharmony_ci if ((ret = c4 - t4)) 126f08c3bdfSopenharmony_ci return ret; 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci return c5 - t5; 129f08c3bdfSopenharmony_ci} 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ciconst char *tst_kvcmp_distname(const char *kver) 132f08c3bdfSopenharmony_ci{ 133f08c3bdfSopenharmony_ci static char distname[64]; 134f08c3bdfSopenharmony_ci char *ret = distname; 135f08c3bdfSopenharmony_ci char *p = distname; 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci if (strstr(kver, ".el7")) 138f08c3bdfSopenharmony_ci return "RHEL7"; 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci if (strstr(kver, ".el8")) 141f08c3bdfSopenharmony_ci return "RHEL8"; 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ci if (strstr(kver, ".el9")) 144f08c3bdfSopenharmony_ci return "RHEL9"; 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci if (access(OSRELEASE_PATH, F_OK) != -1) { 147f08c3bdfSopenharmony_ci SAFE_FILE_LINES_SCANF(NULL, OSRELEASE_PATH, "ID=%s", distname); 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci if (p[0] == '"') { 150f08c3bdfSopenharmony_ci ret = distname + 1; 151f08c3bdfSopenharmony_ci p = ret; 152f08c3bdfSopenharmony_ci } 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci while (*p) { 155f08c3bdfSopenharmony_ci if (*p == '"') { 156f08c3bdfSopenharmony_ci *p = 0; 157f08c3bdfSopenharmony_ci break; 158f08c3bdfSopenharmony_ci } 159f08c3bdfSopenharmony_ci *p = toupper((unsigned char)*p); 160f08c3bdfSopenharmony_ci p++; 161f08c3bdfSopenharmony_ci } 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci return ret; 164f08c3bdfSopenharmony_ci } 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci return NULL; 167f08c3bdfSopenharmony_ci} 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ciint tst_kvercmp2(int r1, int r2, int r3, struct tst_kern_exv *vers) 170f08c3bdfSopenharmony_ci{ 171f08c3bdfSopenharmony_ci int i; 172f08c3bdfSopenharmony_ci const char *kver; 173f08c3bdfSopenharmony_ci struct utsname uval; 174f08c3bdfSopenharmony_ci const char *cur_dist_name; 175f08c3bdfSopenharmony_ci 176f08c3bdfSopenharmony_ci uname(&uval); 177f08c3bdfSopenharmony_ci kver = uval.release; 178f08c3bdfSopenharmony_ci cur_dist_name = tst_kvcmp_distname(kver); 179f08c3bdfSopenharmony_ci 180f08c3bdfSopenharmony_ci if (cur_dist_name == NULL) 181f08c3bdfSopenharmony_ci return tst_kvercmp(r1, r2, r3); 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_ci for (i = 0; vers[i].dist_name; i++) { 184f08c3bdfSopenharmony_ci if (!strcmp(vers[i].dist_name, cur_dist_name)) { 185f08c3bdfSopenharmony_ci tst_resm(TINFO, "Detected %s using kernel version %s", 186f08c3bdfSopenharmony_ci cur_dist_name, kver); 187f08c3bdfSopenharmony_ci return tst_kvexcmp(vers[i].extra_ver, kver); 188f08c3bdfSopenharmony_ci } 189f08c3bdfSopenharmony_ci } 190f08c3bdfSopenharmony_ci 191f08c3bdfSopenharmony_ci return tst_kvcmp(kver, r1, r2, r3); 192f08c3bdfSopenharmony_ci} 193