libselinux: test for file_contexts.bin format

Check to see if the file whose path is passed to selabel_open() starts
with the file_contexts.bin magic number, and if so, automatically
treat it as a file_contexts.bin file.  This allows one to open
file_contexts.bin formatted files without necessarily having a .bin
file suffix.  This removes the need for the previously added
.bin file suffix test.

Change-Id: I6a0cb303954cc6fa24c437ccc794104859eac24b
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/src/label_file.c b/src/label_file.c
index c90d533..f6ea169 100644
--- a/src/label_file.c
+++ b/src/label_file.c
@@ -97,7 +97,7 @@
 }
 
 static int load_mmap(struct selabel_handle *rec, const char *path,
-						    struct stat *sb)
+		     struct stat *sb, bool isbinary)
 {
 	struct saved_data *data = (struct saved_data *)rec->data;
 	char mmap_path[PATH_MAX + 1];
@@ -111,8 +111,8 @@
 	uint32_t i, magic, version;
 	uint32_t entry_len, stem_map_len, regex_array_len;
 
-	len = strlen(path);
-	if (len > 4 && !strcmp(&path[len-4], ".bin")) {
+	if (isbinary) {
+		len = strlen(path);
 		if (len >= sizeof(mmap_path))
 			return -1;
 		strcpy(mmap_path, path);
@@ -412,6 +412,8 @@
 	char *line_buf = NULL;
 	int rc;
 	char stack_path[PATH_MAX + 1];
+	bool isbinary = false;
+	uint32_t magic;
 
 	/* append the path suffix if we have one */
 	if (suffix) {
@@ -433,6 +435,21 @@
 			errno = EINVAL;
 			return -1;
 		}
+
+		if (fread(&magic, sizeof magic, 1, fp) != 1) {
+			errno = EINVAL;
+			fclose(fp);
+			return -1;
+		}
+
+		if (magic == SELINUX_MAGIC_COMPILED_FCONTEXT) {
+			/* file_contexts.bin format */
+			fclose(fp);
+			fp = NULL;
+			isbinary = true;
+		} else {
+			rewind(fp);
+		}
 	} else {
 		/*
 		 * Text file does not exist, so clear the timestamp
@@ -442,7 +459,7 @@
 		sb.st_mtime = 0;
 	}
 
-	rc = load_mmap(rec, path, &sb);
+	rc = load_mmap(rec, path, &sb, isbinary);
 	if (rc == 0)
 		goto out;