1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * This file is part of libmount from util-linux project.
4  *
5  * Copyright (C) 2008-2018 Karel Zak <kzak@redhat.com>
6  *
7  * libmount is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or
10  * (at your option) any later version.
11  */
12 
13 /**
14  * SECTION: version-utils
15  * @title: Version functions
16  * @short_description: functions to get the library version.
17  */
18 
19 #include <ctype.h>
20 
21 #include "mountP.h"
22 
23 static const char *lib_version = LIBMOUNT_VERSION;
24 static const char *lib_features[] = {
25 #ifdef HAVE_LIBSELINUX
26 	"selinux",
27 #endif
28 #ifdef HAVE_SMACK
29 	"smack",
30 #endif
31 #ifdef HAVE_BTRFS_SUPPORT
32 	"btrfs",
33 #endif
34 #ifdef HAVE_CRYPTSETUP
35 	"verity",
36 #endif
37 #ifdef USE_LIBMOUNT_SUPPORT_MTAB
38 	"mtab",
39 #endif
40 #ifdef USE_LIBMOUNT_SUPPORT_NAMESPACES
41 	"namespaces",
42 #endif
43 #if !defined(NDEBUG)
44 	"assert",	/* libc assert.h stuff */
45 #endif
46 	"debug",	/* always enabled */
47 	NULL
48 };
49 
50 /**
51  * mnt_parse_version_string:
52  * @ver_string: version string (e.g "2.18.0")
53  *
54  * Returns: release version code.
55  */
mnt_parse_version_string(const char * ver_string)56 int mnt_parse_version_string(const char *ver_string)
57 {
58 	const char *cp;
59 	int version = 0;
60 
61 	assert(ver_string);
62 
63 	for (cp = ver_string; *cp; cp++) {
64 		if (*cp == '.')
65 			continue;
66 		if (!isdigit(*cp))
67 			break;
68 		version = (version * 10) + (*cp - '0');
69 	}
70 	return version;
71 }
72 
73 /**
74  * mnt_get_library_version:
75  * @ver_string: return pointer to the static library version string if not NULL
76  *
77  * Returns: release version number.
78  */
mnt_get_library_version(const char ** ver_string)79 int mnt_get_library_version(const char **ver_string)
80 {
81 	if (ver_string)
82 		*ver_string = lib_version;
83 
84 	return mnt_parse_version_string(lib_version);
85 }
86 
87 /**
88  * mnt_get_library_features:
89  * @features: returns a pointer to the static array of strings, the array is
90  *            terminated by NULL.
91  *
92  * Returns: number of items in the features array not including the last NULL,
93  *          or less than zero in case of error
94  *
95  * Example:
96  * <informalexample>
97  *   <programlisting>
98  *	const char **features;
99  *
100  *	mnt_get_library_features(&features);
101  *	while (features && *features)
102  *		printf("%s\n", *features++);
103  *   </programlisting>
104  * </informalexample>
105  *
106  */
mnt_get_library_features(const char *** features)107 int mnt_get_library_features(const char ***features)
108 {
109 	if (!features)
110 		return -EINVAL;
111 
112 	*features = lib_features;
113 	return ARRAY_SIZE(lib_features) - 1;
114 }
115 
116 #ifdef TEST_PROGRAM
test_version(struct libmnt_test * ts,int argc,char * argv[])117 static int test_version(struct libmnt_test *ts, int argc, char *argv[])
118 {
119 	const char *ver;
120 	const char **features;
121 
122 	if (argc == 2)
123 		printf("Your version: %d\n",
124 				mnt_parse_version_string(argv[1]));
125 
126 	mnt_get_library_version(&ver);
127 
128 	printf("Library version: %s\n", ver);
129 	printf("Library API version: " LIBMOUNT_VERSION "\n");
130 	printf("Library features:");
131 
132 	mnt_get_library_features(&features);
133 	while (features && *features)
134 		printf(" %s", *features++);
135 
136 	printf("\n");
137 
138 	if (mnt_get_library_version(NULL) ==
139 			mnt_parse_version_string(LIBMOUNT_VERSION))
140 		return 0;
141 
142 	return -1;
143 }
144 
main(int argc,char * argv[])145 int main(int argc, char *argv[])
146 {
147 	struct libmnt_test ts[] = {
148 		{ "--print", test_version, "print versions" },
149 		{ NULL }
150 	};
151 
152 	return mnt_run_test(ts, argc, argv);
153 }
154 #endif
155