From nobody Sun Feb 8 06:05:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=linux.ibm.com ARC-Seal: i=1; a=rsa-sha256; t=1589215386; cv=none; d=zohomail.com; s=zohoarc; b=KJVA8LXMBC5lF3rWYpqc/5g/DNINaGPBFzYbBhpra3vKSJzSiEG4LH8FivBaF44DC8kQFCxyFFQ8wxzmo2YaywI30rivIrTUKKxAPfA/FmiPApOmhWItKXtWSi0iZMXXg9ODZAJcs+7JhYss4iOwYKce+tv98Ifh0KXxIWkZUR8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1589215386; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=z9nT2KJ+ItL/gBo95Tmt1bGvt7ibKwiVpUVmFR9xGsw=; b=mMtvNEOEHAz0ZqTjWpZQx40XHTOrKjpoDLtp5JGhVFDtO4jhGPwJkjMzO6HKjBjgPIGfM8lwGK+qb+tpERibMqM+M63EjkcdF0oRN9L1pE7mKBmFvNar/3Uw5htI/qeMT7xg7xKRbSDZbmge7j/MUg1re5uBJEVc6FKjQLXKEvw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 1589215386044469.86957329003485; Mon, 11 May 2020 09:43:06 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-385-4zoZxuxfOGGJjiF4vPAJRA-1; Mon, 11 May 2020 12:42:39 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B23C9801503; Mon, 11 May 2020 16:42:28 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 92A9F6C799; Mon, 11 May 2020 16:42:28 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 648794CAB0; Mon, 11 May 2020 16:42:28 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 04BGgNBG015781 for ; Mon, 11 May 2020 12:42:23 -0400 Received: by smtp.corp.redhat.com (Postfix) id 359102156A3B; Mon, 11 May 2020 16:42:23 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast05.extmail.prod.ext.rdu2.redhat.com [10.11.55.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 307182156A3C for ; Mon, 11 May 2020 16:42:21 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 31616833B47 for ; Mon, 11 May 2020 16:42:21 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-249-pd2pY7oGP6-tr8w23oISzg-1; Mon, 11 May 2020 12:42:16 -0400 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 04BGXMid137402; Mon, 11 May 2020 12:42:14 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 30ws243jrq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 May 2020 12:42:14 -0400 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.36/8.16.0.36) with SMTP id 04BGYSVH142622; Mon, 11 May 2020 12:42:14 -0400 Received: from ppma03ams.nl.ibm.com (62.31.33a9.ip4.static.sl-reverse.com [169.51.49.98]) by mx0a-001b2d01.pphosted.com with ESMTP id 30ws243jr0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 May 2020 12:42:14 -0400 Received: from pps.filterd (ppma03ams.nl.ibm.com [127.0.0.1]) by ppma03ams.nl.ibm.com (8.16.0.27/8.16.0.27) with SMTP id 04BGerAI025790; Mon, 11 May 2020 16:42:12 GMT Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by ppma03ams.nl.ibm.com with ESMTP id 30wm55mrmv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 May 2020 16:42:11 +0000 Received: from d06av24.portsmouth.uk.ibm.com (mk.ibm.com [9.149.105.60]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 04BGg8lR54395134 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 11 May 2020 16:42:08 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9791B42041; Mon, 11 May 2020 16:42:08 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 47F584204B; Mon, 11 May 2020 16:42:08 +0000 (GMT) Received: from localhost.localdomain (unknown [9.145.43.168]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Mon, 11 May 2020 16:42:08 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1589215384; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=z9nT2KJ+ItL/gBo95Tmt1bGvt7ibKwiVpUVmFR9xGsw=; b=Dbib8ZwCESONTp79zoI8WIO83zeMXIRlFI0ZWZJzdES2X/sWVQWkEWmz4wzmPHGAVKNLpd aO5HufnXhYD4EqAo2hLB8mSgaqw5TbKW4Z/6aoe8PtYWtNWYrtFrDXfpugbDMjgDaTKzBP LkNjdnbvzSCkugii8VZnH+eavbXZXaI= X-MC-Unique: 4zoZxuxfOGGJjiF4vPAJRA-1 X-MC-Unique: pd2pY7oGP6-tr8w23oISzg-1 From: Boris Fiuczynski To: libvir-list@redhat.com, mihajlov@linux.ibm.com, ppinatti@linux.ibm.com, berrange@redhat.com, borntraeger@de.ibm.com, brijesh.singh@amd.com, eskultet@redhat.com Subject: [PATCH 1/6] util: introduce a parser for kernel cmdline arguments Date: Mon, 11 May 2020 18:41:56 +0200 Message-Id: <20200511164201.7954-2-fiuczy@linux.ibm.com> In-Reply-To: <20200511164201.7954-1-fiuczy@linux.ibm.com> References: <20200511164201.7954-1-fiuczy@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-11_08:2020-05-11, 2020-05-11 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 clxscore=1015 suspectscore=2 bulkscore=0 adultscore=0 impostorscore=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 mlxlogscore=999 priorityscore=1501 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005110130 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-loop: libvir-list@redhat.com Cc: danielhb413@gmail.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Paulo de Rezende Pinatti Introduce two utility functions to parse a kernel command line string according to the kernel code parsing rules in order to enable the caller to perform operations such as verifying whether certain argument=3Dvalue combinations are present or retrieving an argument's value. Signed-off-by: Paulo de Rezende Pinatti Reviewed-by: Boris Fiuczynski --- src/libvirt_private.syms | 2 + src/util/virutil.c | 173 +++++++++++++++++++++++++++++++++++++++ src/util/virutil.h | 18 ++++ tests/utiltest.c | 130 +++++++++++++++++++++++++++++ 4 files changed, 323 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 935ef7303b..25b22a3e3f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3428,6 +3428,8 @@ virHostGetDRMRenderNode; virHostHasIOMMU; virIndexToDiskName; virIsDevMapperDevice; +virKernelCmdlineGetValue; +virKernelCmdlineMatchParam; virMemoryLimitIsSet; virMemoryLimitTruncate; virMemoryMaxValue; diff --git a/src/util/virutil.c b/src/util/virutil.c index fb46501142..264aae8d01 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -1725,6 +1725,179 @@ virHostGetDRMRenderNode(void) return ret; } =20 + +#define VIR_IS_CMDLINE_SPACE(value) \ + (g_ascii_isspace(value) || (unsigned char) value =3D=3D 160) + + +static bool virKernelArgsAreEqual(const char *arg1, + const char *arg2, + size_t n) +{ + size_t i; + + for (i =3D 0; i < n; i++) { + if ((arg1[i] =3D=3D '-' && arg2[i] =3D=3D '_') || + (arg1[i] =3D=3D '_' && arg2[i] =3D=3D '-') || (arg1[i] =3D=3D = arg2[i])) { + if (arg1[i] =3D=3D '\0') + return true; + continue; + } + return false; + } + return true; +} + + +/* + * Parse the kernel cmdline and store the value of @arg in @val + * which can be NULL if @arg has no value or if it's not found. + * In addition, store in @next the address right after + * @arg=3D@value for possible further processing. + * + * @arg: kernel command line argument + * @cmdline: kernel command line string to be checked for @arg + * @val: pointer to hold retrieved value of @arg + * @next: pointer to hold address right after @arg=3D@val, will + * point to the string's end (NULL) in case @arg is not found + * + * Returns 0 if @arg is present in @cmdline, 1 otherwise + */ +int virKernelCmdlineGetValue(const char *arg, + const char *cmdline, + char **val, + const char **next) +{ + size_t i =3D 0, param_i; + size_t arg_len =3D strlen(arg); + bool is_quoted, match; + + *next =3D cmdline; + *val =3D NULL; + + while (cmdline[i] !=3D '\0') { + /* remove leading spaces */ + while (VIR_IS_CMDLINE_SPACE(cmdline[i])) + i++; + if (cmdline[i] =3D=3D '"') { + i++; + is_quoted =3D true; + } else { + is_quoted =3D false; + } + for (param_i =3D i; cmdline[param_i]; param_i++) { + if ((VIR_IS_CMDLINE_SPACE(cmdline[param_i]) && !is_quoted) || + cmdline[param_i] =3D=3D '=3D') + break; + if (cmdline[param_i] =3D=3D '"') + is_quoted =3D !is_quoted; + } + if (param_i-i =3D=3D arg_len && virKernelArgsAreEqual(cmdline+i, a= rg, arg_len)) + match =3D true; + else + match =3D false; + /* arg has no value */ + if (cmdline[param_i] !=3D '=3D') { + if (match) { + *next =3D cmdline+param_i; + return 0; + } + i =3D param_i; + continue; + } + param_i++; + if (cmdline[param_i] =3D=3D '\0') + break; + + if (cmdline[param_i] =3D=3D '"') { + param_i++; + is_quoted =3D !is_quoted; + } + i =3D param_i; + + for (; cmdline[param_i]; param_i++) { + if (VIR_IS_CMDLINE_SPACE(cmdline[param_i]) && !is_quoted) + break; + if (cmdline[param_i] =3D=3D '"') + is_quoted =3D !is_quoted; + } + if (match) { + *next =3D cmdline+param_i; + if (cmdline[param_i-1] =3D=3D '"') + *val =3D g_strndup(cmdline+i, param_i-i-1); + else + *val =3D g_strndup(cmdline+i, param_i-i); + return 0; + } + i =3D param_i; + } + *next =3D cmdline+i; + return 1; +} + + +#define VIR_CMDLINE_STR_CMP(kernel_val, caller_val, flags) \ + (((flags & VIR_KERNEL_CMDLINE_FLAGS_CMP_EQ) && \ + STREQ(kernel_val, caller_val)) || ((flags & VIR_KERNEL_CMDLINE_FLAGS= _CMP_PREFIX) && \ + STRPREFIX(kernel_val, caller_val)= )) + + +/* + * Try to match the provided kernel cmdline string with the provided @arg + * and the list @values of possible values according to the matching strat= egy + * defined in @flags. Possible options include: + * - VIR_KERNEL_CMDLINE_FLAGS_CMP_PREFIX: do a substring comparison of val= ues + * (uses size of value provided as input) + * - VIR_KERNEL_CMDLINE_FLAGS_CMP_EQ: do a strict string comparison + * - VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY: first positive match satifies= search + * (in case of multiple argument occurrences) + * - VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST: use the result of last argument= occurence + * (in case of multiple argument occurrences) + * + * + * @cmdline: kernel command line string to be checked for @arg + * @arg: kernel command line argument + * @values: array of possible values to match @arg + * @len_values: size of array, it can be 0 meaning a match will be positiv= e if the + * argument has no value. + * @flags: flag mask defining the strategy for matching and comparing + * + * Returns true if a match is found, false otherwise + */ +bool virKernelCmdlineMatchParam(const char *cmdline, + const char *arg, + const char **values, + size_t len_values, + virKernelCmdlineFlags flags) +{ + bool match =3D false; + size_t i; + const char *next =3D cmdline; + g_autofree char *kval =3D NULL; + + while (next[0] !=3D '\0') { + VIR_FREE(kval); + if (virKernelCmdlineGetValue(arg, next, &kval, &next) !=3D 0) + break; + if (!kval) { + match =3D (len_values =3D=3D 0) ? true : false; + } else { + match =3D false; + for (i =3D 0; i < len_values; i++) { + if (VIR_CMDLINE_STR_CMP(kval, values[i], flags)) { + match =3D true; + break; + } + } + } + if (match && (flags & VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY)) + break; + } + + return match; +} + + /* * Get a password from the console input stream. * The caller must free the returned password. diff --git a/src/util/virutil.h b/src/util/virutil.h index 49b4bf440f..1edb415fbe 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -147,6 +147,24 @@ bool virHostHasIOMMU(void); =20 char *virHostGetDRMRenderNode(void) G_GNUC_NO_INLINE; =20 +typedef enum { + VIR_KERNEL_CMDLINE_FLAGS_CMP_PREFIX =3D 1, + VIR_KERNEL_CMDLINE_FLAGS_CMP_EQ =3D 2, + VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY =3D 4, + VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST =3D 8, +} virKernelCmdlineFlags; + +int virKernelCmdlineGetValue(const char *arg, + const char *cmdline, + char **val, + const char **next); + +bool virKernelCmdlineMatchParam(const char *cmdline, + const char *arg, + const char **values, + size_t len_values, + virKernelCmdlineFlags flags); + /** * VIR_ASSIGN_IS_OVERFLOW: * @rvalue: value that is checked (evaluated twice) diff --git a/tests/utiltest.c b/tests/utiltest.c index 5ae04585cb..1edc6a728e 100644 --- a/tests/utiltest.c +++ b/tests/utiltest.c @@ -254,6 +254,134 @@ testOverflowCheckMacro(const void *data G_GNUC_UNUSED) } =20 =20 +struct testKernelCmdlineGetValueData +{ + const char *cmdline; + const char *arg; + int rc; + const char *val; + size_t next; +}; + +static struct testKernelCmdlineGetValueData kEntries[] =3D { + { "arg1 arg2 arg3=3Dval1", "arg4", = 1, NULL, 19 }, + { "arg1=3Dval1 arg2 arg3=3Dval3 arg4", "arg2", = 0, NULL, 14 }, + { "arg1=3Dval1 arg2 arg3=3Dval3 arg4", "arg3", = 0, "val3", 24 }, + { "arg1=3Dval1 arg2 arg-3=3Dval3 arg4", "arg_3", = 0, "val3", 25 }, + { "arg1=3Dval1 arg2 arg_3=3Dval3 arg4", "arg-3", = 0, "val3", 25 }, + { "arg1=3Dval1 arg2 arg_3=3Dval3 arg4", "arg_3", = 0, "val3", 25 }, + { "arg1=3Dval1 arg2 arg-3=3Dval3 arg4", "arg-3", = 0, "val3", 25 }, + { "arg1=3Dval1 arg2=3D\"value with spaces\" arg3=3Dval3", "arg2", = 0, "value with spaces", 34 }, + { "arg1=3Dval1 arg2=3D\"value with spaces\" arg3=3Dval3", "arg3", = 0, "val3", 44 }, + { "arg1=3Dval1 \"arg2=3Dvalue with spaces\" arg3=3Dval3", "arg2", = 0, "value with spaces", 34 }, + { "arg1=3Dval1 \"arg2=3Dvalue with spaces\" arg3=3Dval3", "arg3", = 0, "val3", 44 }, + { "arg1=3Dval1 arg2=3D\"val\"ue arg3", "arg2", = 0, "val\"ue", 22 }, + { "arg1=3Dval1 arg2=3D\"val\"ue arg3\" escaped=3Dval2\"", "arg3\" esca= ped", 0, "val2", 42 }, + { "arg1=3Dval1 arg2longer=3Dsomeval arg2=3Dval2 arg3", "arg2", = 0, "val2", 38 }, +}; + +static int +testKernelCmdlineGetValue(const void *data G_GNUC_UNUSED) +{ + int rc; + char *val =3D NULL; + const char *next; + size_t i; + + for (i =3D 0; i < G_N_ELEMENTS(kEntries); ++i) { + VIR_FREE(val); + + rc =3D virKernelCmdlineGetValue(kEntries[i].arg, kEntries[i].cmdli= ne, + &val, &next); + + if (rc !=3D kEntries[i].rc || STRNEQ_NULLABLE(val, kEntries[i].val= ) || + (next - kEntries[i].cmdline) !=3D kEntries[i].next) { + VIR_TEST_DEBUG("\nKernel cmdline [%s]", kEntries[i].cmdline); + VIR_TEST_DEBUG("Kernel argument [%s]", kEntries[i].arg); + VIR_TEST_DEBUG("Expect rc [%d]", kEntries[i].rc); + VIR_TEST_DEBUG("Actual rc [%d]", rc); + VIR_TEST_DEBUG("Expect value [%s]", kEntries[i].val); + VIR_TEST_DEBUG("Actual value [%s]", val); + VIR_TEST_DEBUG("Expect next index [%lu]", kEntries[i].next); + VIR_TEST_DEBUG("Actual next index [%lu]", + (size_t)(next - kEntries[i].cmdline)); + + VIR_FREE(val); + + return -1; + } + } + + VIR_FREE(val); + + return 0; +} + + +struct testKernelCmdlineMatchData +{ + const char *cmdline; + const char *arg; + const char *values[2]; + virKernelCmdlineFlags flags; + bool result; +}; + +static struct testKernelCmdlineMatchData kMatchEntries[] =3D { + {"arg1 myarg=3Dno arg2=3Dval2 myarg=3Dyes arg4=3Dval4 myarg=3Dno arg5"= , "myarg", {"1", "y"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY | VIR_KERN= EL_CMDLINE_FLAGS_CMP_EQ, false }, + {"arg1 myarg=3Dno arg2=3Dval2 myarg=3Dyes arg4=3Dval4 myarg=3Dno arg5"= , "myarg", {"on", "yes"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY | VIR_KERN= EL_CMDLINE_FLAGS_CMP_EQ, true }, + {"arg1 myarg=3Dno arg2=3Dval2 myarg=3Dyes arg4=3Dval4 myarg=3Dno arg5"= , "myarg", {"1", "y"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY | VIR_KERN= EL_CMDLINE_FLAGS_CMP_PREFIX, true }, + {"arg1 myarg=3Dno arg2=3Dval2 myarg=3Dyes arg4=3Dval4 myarg=3Dno arg5"= , "myarg", {"a", "b"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY | VIR_KERN= EL_CMDLINE_FLAGS_CMP_PREFIX, false }, + {"arg1 myarg=3Dno arg2=3Dval2 myarg=3Dyes arg4=3Dval4 myarg=3Dno arg5"= , "myarg", {"on", "yes"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST | VIR_KERNEL= _CMDLINE_FLAGS_CMP_EQ, false}, + {"arg1 myarg=3Dno arg2=3Dval2 myarg=3Dyes arg4=3Dval4 myarg=3Dno arg5"= , "myarg", {"1", "y"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST | VIR_KERNEL= _CMDLINE_FLAGS_CMP_PREFIX, false}, + {"arg1 myarg=3Dno arg2=3Dval2 arg4=3Dval4 myarg=3Dyes arg5", = "myarg", {"on", "yes"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST | VIR_KERNEL_C= MDLINE_FLAGS_CMP_EQ, true }, + {"arg1 myarg=3Dno arg2=3Dval2 arg4=3Dval4 myarg=3Dyes arg5", = "myarg", {"1", "y"}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST | VIR_KERNEL_C= MDLINE_FLAGS_CMP_PREFIX, true }, + {"arg1 myarg=3Dno arg2=3Dval2 arg4=3Dval4 myarg arg5", "m= yarg", {NULL, NULL}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST, = true }, + {"arg1 myarg arg2=3Dval2 arg4=3Dval4 myarg=3Dyes arg5", "m= yarg", {NULL, NULL}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STICKY, = true }, + {"arg1 myarg arg2=3Dval2 arg4=3Dval4 myarg=3Dyes arg5", "m= yarg", {NULL, NULL}, VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST, = false }, +}; + + +static int +testKernelCmdlineMatchParam(const void *data G_GNUC_UNUSED) +{ + bool result; + size_t i, lenValues; + + for (i =3D 0; i < G_N_ELEMENTS(kMatchEntries); ++i) { + if (kMatchEntries[i].values[0] =3D=3D NULL) + lenValues =3D 0; + else + lenValues =3D G_N_ELEMENTS(kMatchEntries[i].values); + + result =3D virKernelCmdlineMatchParam(kMatchEntries[i].cmdline, + kMatchEntries[i].arg, + kMatchEntries[i].values, + lenValues, + kMatchEntries[i].flags); + + if (result !=3D kMatchEntries[i].result) { + VIR_TEST_DEBUG("\nKernel cmdline [%s]", kMatchEntries[i].cmdli= ne); + VIR_TEST_DEBUG("Kernel argument [%s]", kMatchEntries[i].arg); + VIR_TEST_DEBUG("Kernel values [%s] [%s]", kMatchEntries[i].val= ues[0], + kMatchEntries[i].values[1]); + if (kMatchEntries[i].flags & VIR_KERNEL_CMDLINE_FLAGS_CMP_PREF= IX) + VIR_TEST_DEBUG("Flag [VIR_KERNEL_CMDLINE_FLAGS_CMP_PREFIX]= "); + if (kMatchEntries[i].flags & VIR_KERNEL_CMDLINE_FLAGS_CMP_EQ) + VIR_TEST_DEBUG("Flag [VIR_KERNEL_CMDLINE_FLAGS_CMP_EQ]"); + if (kMatchEntries[i].flags & VIR_KERNEL_CMDLINE_FLAGS_SEARCH_S= TICKY) + VIR_TEST_DEBUG("Flag [VIR_KERNEL_CMDLINE_FLAGS_SEARCH_STIC= KY]"); + if (kMatchEntries[i].flags & VIR_KERNEL_CMDLINE_FLAGS_SEARCH_L= AST) + VIR_TEST_DEBUG("Flag [VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST= ]"); + VIR_TEST_DEBUG("Expect result [%d]", kMatchEntries[i].result); + VIR_TEST_DEBUG("Actual result [%d]", result); + + return -1; + } + } + + return 0; +} =20 =20 static int @@ -277,6 +405,8 @@ mymain(void) DO_TEST(ParseVersionString); DO_TEST(RoundValueToPowerOfTwo); DO_TEST(OverflowCheckMacro); + DO_TEST(KernelCmdlineGetValue); + DO_TEST(KernelCmdlineMatchParam); =20 return result =3D=3D 0 ? EXIT_SUCCESS : EXIT_FAILURE; } --=20 2.25.1