seamendc: prefetch binary policy in memory before parsing

This optimization improves the runtime of seamendc by ~6-7ms.

Bug: 236691128
Test: atest seamendc-test && atest SeamendcHostTest
Change-Id: Id1e86a5f51d035fac415a0e6ae05b99b3bd774d4
diff --git a/tools/seamendc.c b/tools/seamendc.c
index 2e49c1b..cd79c76 100644
--- a/tools/seamendc.c
+++ b/tools/seamendc.c
@@ -9,6 +9,7 @@
 #include <cil/cil.h>
 #include <cil/android.h>
 #include <sepol/policydb.h>
+#include "sepol/handle.h"
 
 void usage(const char *prog)
 {
@@ -26,10 +27,17 @@
 
 /*
  * Read binary policy file from path into the allocated pdb.
+ *
+ * We first read the binary policy into memory, and then we parse it to a
+ * policydb object using sepol_policydb_from_image. This combination is slightly
+ * faster than using sepol_policydb_read that reads the binary file in small
+ * chunks at a time.
  */
 static int read_binary_policy(char *path, sepol_policydb_t *pdb)
 {
     int rc = SEPOL_OK;
+    char *buff = NULL;
+    sepol_handle_t *handle = NULL;
 
     FILE *file = fopen(path, "r");
     if (!file) {
@@ -44,24 +52,38 @@
         fprintf(stderr, "Could not stat %s: %s.\n", path, strerror(errno));
         goto exit;
     }
-    if (!binarydata.st_size) {
+
+    uint32_t file_size = binarydata.st_size;
+    if (!file_size) {
         fprintf(stderr, "Binary policy file is empty.\n");
         rc = SEPOL_ERR;
         goto exit;
     }
 
-    struct sepol_policy_file *pf = NULL;
-    rc = sepol_policy_file_create(&pf);
-    if (rc != 0) {
-        fprintf(stderr, "Failed to create policy file: %d.\n", rc);
+    buff = malloc(file_size);
+    if (buff == NULL) {
+        perror("malloc failed");
+        rc = SEPOL_ERR;
         goto exit;
     }
-    sepol_policy_file_set_fp(pf, file);
 
-    rc = sepol_policydb_read(pdb, pf);
+    rc = fread(buff, file_size, 1, file);
+    if (rc != 1) {
+        fprintf(stderr, "Failure reading %s: %s.\n", path, strerror(errno));
+        rc = SEPOL_ERR;
+        goto exit;
+    }
+
+    handle = sepol_handle_create();
+    if (!handle) {
+        perror("Could not create policy handle");
+        rc = SEPOL_ERR;
+        goto exit;
+    }
+
+    rc = sepol_policydb_from_image(handle, buff, file_size, pdb);
     if (rc != 0) {
         fprintf(stderr, "Failed to read binary policy: %d.\n", rc);
-        goto exit;
     }
 
 exit:
@@ -69,6 +91,10 @@
         perror("Failure closing binary file");
         rc = SEPOL_ERR;
     }
+    if(handle != NULL) {
+        sepol_handle_destroy(handle);
+    }
+    free(buff);
     return rc;
 }