File libsemanage-version-numbers.patch of Package libsemanage.10234

diff --git libsemanage-2.5/include/semanage/modules.h libsemanage-2.5/include/semanage/modules.h
index 4b93e54..50940e2 100644
--- libsemanage-2.5/include/semanage/modules.h
+++ libsemanage-2.5/include/semanage/modules.h
@@ -39,7 +39,7 @@ int semanage_module_install_file(semanage_handle_t *,
 int semanage_module_remove(semanage_handle_t *, char *module_name);
 
 /* semanage_module_info is for getting information on installed
-   modules, only name at this time */
+   modules, only name and version at this time */
 typedef struct semanage_module_info semanage_module_info_t;
 
 /* Look up a module using @modkey. The module's raw data is returned as a
@@ -64,6 +64,7 @@ void semanage_module_info_datum_destroy(semanage_module_info_t *);
 semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list,
 						 int n);
 const char *semanage_module_get_name(semanage_module_info_t *);
+const char *semanage_module_get_version(semanage_module_info_t *);
 
 /* Module Info */
 
@@ -104,6 +105,14 @@ int semanage_module_info_get_name(semanage_handle_t *sh,
 				  semanage_module_info_t *modinfo,
 				  const char **name);
 
+/* Get @module_version from @modinfo. Caller should not free @module_version.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_get_version(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char **version);
+
 /* Get @lang_ext from @modinfo. Caller should not free @lang_ext.
  *
  * Returns 0 on success and -1 on error.
@@ -138,6 +147,14 @@ int semanage_module_info_set_name(semanage_handle_t *sh,
 				  semanage_module_info_t *modinfo,
 				  const char *name);
 
+/* Set @version in @modinfo.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int semanage_module_info_set_version(semanage_handle_t *sh,
+				      semanage_module_info_t *modinfo,
+				      const char *version);
+
 /* Set @lang_ext in @modinfo.
  *
  * Returns 0 on success and -1 on error.
diff --git libsemanage-2.5/src/direct_api.c libsemanage-2.5/src/direct_api.c
index 2187b65..db29430 100644
--- libsemanage-2.5/src/direct_api.c
+++ libsemanage-2.5/src/direct_api.c
@@ -363,6 +363,74 @@ static int semanage_direct_begintrans(semanage_handle_t * sh)
 
 /********************* utility functions *********************/
 
+/* Takes a module stored in 'module_data' and parses its headers.
+ * Sets reference variables 'module_name' to module's name, and
+ * 'version' to module's version.  The caller is responsible for
+ * free()ing 'module_name', and 'version'; they will be
+ * set to NULL upon entering this function.  Returns 0 on success, -1
+ * if out of memory.
+ */
+static int parse_module_headers(semanage_handle_t * sh, char *module_data,
+                               size_t data_len, char **module_name,
+                               char **version)
+{
+       struct sepol_policy_file *pf;
+       int file_type;
+       *module_name = *version = NULL;
+
+       if (sepol_policy_file_create(&pf)) {
+               ERR(sh, "Out of memory!");
+               return -1;
+       }
+       sepol_policy_file_set_mem(pf, module_data, data_len);
+       sepol_policy_file_set_handle(pf, sh->sepolh);
+       if (module_data != NULL && data_len > 0)
+           sepol_module_package_info(pf, &file_type, module_name,
+                                     version);
+       sepol_policy_file_free(pf);
+
+       return 0;
+}
+
+/* Takes a base module stored in 'module_data' and parse its headers.
+ * Returns 0 on success, -1 if out of memory, or -2 if data did not
+ * represent a module.
+ */
+static int parse_base_headers(semanage_handle_t * sh,
+                             char *module_data, size_t data_len)
+{
+       struct sepol_policy_file *pf;
+       char *module_name = NULL, *version = NULL;
+       int file_type;
+
+       if (sepol_policy_file_create(&pf)) {
+               ERR(sh, "Out of memory!");
+               return -1;
+       }
+       sepol_policy_file_set_mem(pf, module_data, data_len);
+       sepol_policy_file_set_handle(pf, sh->sepolh);
+       if (module_data == NULL ||
+           data_len == 0 ||
+           sepol_module_package_info(pf, &file_type,
+                                     &module_name, &version) == -1) {
+               sepol_policy_file_free(pf);
+               ERR(sh, "Could not parse base module data.");
+               return -2;
+       }
+       sepol_policy_file_free(pf);
+       free(module_name);
+       free(version);
+       if (file_type != SEPOL_POLICY_BASE) {
+               if (file_type == SEPOL_POLICY_MOD)
+                       ERR(sh,
+                           "Received a non-base module, expected a base module.");
+               else
+                       ERR(sh, "Data did not represent a module.");
+               return -2;
+       }
+       return 0;
+}
+
 #include <stdlib.h>
 #include <bzlib.h>
 #include <string.h>
@@ -2075,6 +2143,31 @@ static int semanage_direct_get_module_info(semanage_handle_t *sh,
 	free(tmp);
 	tmp = NULL;
 
+	if (strcmp((*modinfo)->lang_ext, "pp") == 0) {
+		/* try to get a module_version from hll file */
+		int data_len, compressed = 0;
+		char *data = NULL;
+		char fhll[PATH_MAX];
+		ret = semanage_module_get_path(sh,
+					       *modinfo,
+					       SEMANAGE_MODULE_PATH_HLL,
+					       fhll,
+					       sizeof(fhll));
+		if (ret == 0) {
+			if ((data_len = map_file(sh, fhll, &data, &compressed)) > 0) {
+
+				char *module_name = NULL;
+				char *version = NULL;
+				ret = parse_module_headers(sh, data, data_len, &module_name, &version);
+				if (ret == 0 && version != NULL) {
+					ret = semanage_module_info_set_version(sh, *modinfo, version);
+				}
+				free(module_name);
+				free(version);
+				munmap(data, data_len);
+			}
+		}
+	}
 	if (fclose(fp) != 0) {
 		ERR(sh,
 		    "Unable to close %s module lang ext file.",
diff --git libsemanage-2.5/src/libsemanage.map libsemanage-2.5/src/libsemanage.map
index 34b553d..0da1857 100644
--- libsemanage-2.5/src/libsemanage.map
+++ libsemanage-2.5/src/libsemanage.map
@@ -40,6 +40,7 @@ LIBSEMANAGE_1.1 {
 	  semanage_module_info_destroy;
 	  semanage_module_info_get_priority;
 	  semanage_module_info_get_name;
+	  semanage_module_info_get_version;
 	  semanage_module_info_get_lang_ext;
 	  semanage_module_info_get_enabled;
 	  semanage_module_info_set_priority;
diff --git libsemanage-2.5/src/module_internal.h libsemanage-2.5/src/module_internal.h
index c99f6c2..d62091a 100644
--- libsemanage-2.5/src/module_internal.h
+++ libsemanage-2.5/src/module_internal.h
@@ -11,10 +11,12 @@ hidden_proto(semanage_module_get_name)
     hidden_proto(semanage_module_info_destroy)
     hidden_proto(semanage_module_info_get_priority)
     hidden_proto(semanage_module_info_get_name)
+    hidden_proto(semanage_module_info_get_version)
     hidden_proto(semanage_module_info_get_lang_ext)
     hidden_proto(semanage_module_info_get_enabled)
     hidden_proto(semanage_module_info_set_priority)
     hidden_proto(semanage_module_info_set_name)
+    hidden_proto(semanage_module_info_set_version)
     hidden_proto(semanage_module_info_set_lang_ext)
     hidden_proto(semanage_module_info_set_enabled)
     hidden_proto(semanage_module_key_create)
diff --git libsemanage-2.5/src/modules.c libsemanage-2.5/src/modules.c
index 90c5e49..85285a1 100644
--- libsemanage-2.5/src/modules.c
+++ libsemanage-2.5/src/modules.c
@@ -291,6 +291,7 @@ int semanage_module_info_destroy(semanage_handle_t *sh,
 	}
 
 	free(modinfo->name);
+	free(modinfo->module_version);
 	free(modinfo->lang_ext);
 
 	return semanage_module_info_init(sh, modinfo);
@@ -306,6 +307,7 @@ int semanage_module_info_init(semanage_handle_t *sh,
 
 	modinfo->priority = 0;
 	modinfo->name = NULL;
+	modinfo->module_version = NULL;
 	modinfo->lang_ext = NULL;
 	modinfo->enabled = -1;
 
@@ -341,6 +343,14 @@ int semanage_module_info_clone(semanage_handle_t *sh,
 		goto cleanup;
 	}
 
+	if (source->module_version != NULL) {
+		ret = semanage_module_info_set_version(sh, target, source->module_version);
+		if (ret != 0) {
+			status = -1;
+			goto cleanup;
+		}
+	}
+
 	ret = semanage_module_info_set_lang_ext(sh, target, source->lang_ext);
 	if (ret != 0) {
 		status = -1;
@@ -388,6 +398,21 @@ int semanage_module_info_get_name(semanage_handle_t *sh,
 
 hidden_def(semanage_module_info_get_name)
 
+int semanage_module_info_get_version(semanage_handle_t *sh,
+				  semanage_module_info_t *modinfo,
+				  const char **version)
+{
+	assert(sh);
+	assert(modinfo);
+	assert(version);
+
+	*version = modinfo->module_version;
+
+	return 0;
+}
+
+hidden_def(semanage_module_info_get_version)
+
 int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
 				      semanage_module_info_t *modinfo,
 				      const char **lang_ext)
@@ -470,6 +495,37 @@ int semanage_module_info_set_name(semanage_handle_t *sh,
 
 hidden_def(semanage_module_info_set_name)
 
+int semanage_module_info_set_version(semanage_handle_t *sh,
+                                    semanage_module_info_t *modinfo,
+                                    const char *version)
+{
+       assert(sh);
+       assert(modinfo);
+       assert(version);
+
+       char * tmp;
+
+       /* Verify version */
+
+       if (semanage_module_validate_version(version) < 0) {
+               errno = 0;
+               return -1;
+       }
+
+       tmp = strdup(version);
+       if (!tmp) {
+               return -1;
+       }
+
+       free(modinfo->module_version);
+       modinfo->module_version = tmp;
+
+       return 0;
+}
+
+hidden_def(semanage_module_info_set_version)
+
+
 int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
 				      semanage_module_info_t *modinfo,
 				      const char *lang_ext)
@@ -1064,6 +1120,49 @@ exit:
 	return status;
 }
 
+/* Validate version.
+ *
+ * A version must match the following regular expression to be
+ * considered valid:
+ *
+ * ^[:print:]+$
+ *
+ * returns 0 if version is valid, returns -1 otherwise.
+ */
+int semanage_module_validate_version(const char *version)
+{
+	int status = 0;
+
+	if (version == NULL) {
+		status = -1;
+		goto exit;
+	}
+
+	/* must start with a printable char */
+	if (!isprint(*version)) {
+		status = -1;
+		goto exit;
+	}
+
+	/* everything else must be printable */
+#define ISVALIDCHAR(c) (isprint(c))
+
+	for (version++; *version; version++) {
+		if (ISVALIDCHAR(*version)) {
+			continue;
+		}
+		status = -1;
+		goto exit;
+	}
+
+#undef ISVALIDCHAR
+
+exit:
+	return status;
+}
+
+
+
 int semanage_module_get_module_info(semanage_handle_t *sh,
 				    const semanage_module_key_t *modkey,
 				    semanage_module_info_t **modinfo)
diff --git libsemanage-2.5/src/modules.h libsemanage-2.5/src/modules.h
index 8a5c01f..ee3d51d 100644
--- libsemanage-2.5/src/modules.h
+++ libsemanage-2.5/src/modules.h
@@ -44,6 +44,7 @@ struct semanage_module_info {
 	uint16_t priority;	/* key, module priority */
 	char *name;		/* key, module name */
 	char *lang_ext;		/* module source language extension */
+	char *module_version;	/* module version, applies only for pp modules  */
 	int enabled;		/* module enabled/disabled status */
 };
 
openSUSE Build Service is sponsored by