Refactor: disambiguate fs-verity helper functions

The original code mixes 3 operations (enable, measure, and enabling
status) in the helper functions. Refactoring to match the underlying
syscalls.

Note that the "original measureFsVerity" returns the status of fs-verity
for the file by measuring the file, which involves a hash operation.
This change also replaces it with a query to the file attribute.

Bug: 258061812
Test: odsign_e2e_tests
Change-Id: Iae3994351dc6a92fc8c299d942b6e95f8ed12ef3
diff --git a/ondevice-signing/VerityUtils.cpp b/ondevice-signing/VerityUtils.cpp
index cd9a1ea..d5c7299 100644
--- a/ondevice-signing/VerityUtils.cpp
+++ b/ondevice-signing/VerityUtils.cpp
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include "android-base/errors.h"
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
@@ -127,20 +128,6 @@
     }
 };
 
-static Result<void> measureFsVerity(int fd, const fsverity_digest* digest) {
-    if (ioctl(fd, FS_IOC_MEASURE_VERITY, digest) != 0) {
-        if (errno == ENODATA) {
-            return Error() << "File is not in fs-verity";
-        } else {
-            return ErrnoError() << "Failed to FS_IOC_MEASURE_VERITY";
-        }
-    }
-
-    return {};
-}
-
-}  // namespace
-
 template <typename T> using trailing_unique_ptr = std::unique_ptr<T, DeleteAsPODArray<T>>;
 
 template <typename T>
@@ -150,6 +137,32 @@
     return trailing_unique_ptr<T>{ptr};
 }
 
+static Result<std::string> measureFsVerity(int fd) {
+    auto d = makeUniqueWithTrailingData<fsverity_digest>(FS_VERITY_MAX_DIGEST_SIZE);
+    d->digest_size = FS_VERITY_MAX_DIGEST_SIZE;
+
+    if (ioctl(fd, FS_IOC_MEASURE_VERITY, d.get()) != 0) {
+        if (errno == ENODATA) {
+            return Error() << "File is not in fs-verity";
+        } else {
+            return ErrnoError() << "Failed to FS_IOC_MEASURE_VERITY";
+        }
+    }
+
+    return toHex({&d->digest[0], &d->digest[d->digest_size]});
+}
+
+static Result<std::string> measureFsVerity(const std::string& path) {
+    unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (!fd.ok()) {
+        return ErrnoError() << "Failed to open " << path;
+    }
+
+    return measureFsVerity(fd.get());
+}
+
+}  // namespace
+
 static Result<std::vector<uint8_t>> signDigest(const SigningKey& key,
                                                const std::vector<uint8_t>& digest) {
     auto d = makeUniqueWithTrailingData<fsverity_formatted_digest>(digest.size());
@@ -209,30 +222,12 @@
     return toHex(digest.value());
 }
 
-static Result<std::string> isFileInVerity(int fd) {
-    auto d = makeUniqueWithTrailingData<fsverity_digest>(FS_VERITY_MAX_DIGEST_SIZE);
-    d->digest_size = FS_VERITY_MAX_DIGEST_SIZE;
-
-    const auto& status = measureFsVerity(fd, d.get());
-    if (!status.ok()) {
-        return status.error();
+static Result<bool> isFileInVerity(int fd) {
+    unsigned int flags;
+    if (ioctl(fd, FS_IOC_GETFLAGS, &flags) < 0) {
+        return ErrnoError() << "ioctl(FS_IOC_GETFLAGS) failed";
     }
-
-    return toHex({&d->digest[0], &d->digest[d->digest_size]});
-}
-
-static Result<std::string> isFileInVerity(const std::string& path) {
-    unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
-    if (!fd.ok()) {
-        return ErrnoError() << "Failed to open " << path;
-    }
-
-    auto digest = isFileInVerity(fd.get());
-    if (!digest.ok()) {
-        return Error() << digest.error() << ": " << path;
-    }
-
-    return digest;
+    return (flags & FS_VERITY_FL) != 0;
 }
 
 Result<std::map<std::string, std::string>> addFilesToVerityRecursive(const std::string& path,
@@ -247,18 +242,15 @@
             if (!fd.ok()) {
                 return ErrnoError() << "Failed to open " << path;
             }
-            auto digest = isFileInVerity(fd);
-            if (!digest.ok()) {
+            auto enabled = OR_RETURN(isFileInVerity(fd));
+            if (!enabled) {
                 LOG(INFO) << "Adding " << it->path() << " to fs-verity...";
-                auto result = enableFsVerity(fd, key);
-                if (!result.ok()) {
-                    return result.error();
-                }
-                digests[it->path()] = *result;
+                OR_RETURN(enableFsVerity(fd, key));
             } else {
                 LOG(INFO) << it->path() << " was already in fs-verity.";
-                digests[it->path()] = *digest;
             }
+            auto digest = OR_RETURN(measureFsVerity(fd));
+            digests[it->path()] = digest;
         }
     }
     if (ec) {
@@ -282,14 +274,6 @@
     if (!enable.ok()) {
         return enable.error();
     }
-
-    auto digest = makeUniqueWithTrailingData<fsverity_digest>(FS_VERITY_MAX_DIGEST_SIZE);
-    digest->digest_size = FS_VERITY_MAX_DIGEST_SIZE;
-    const auto& measure = measureFsVerity(fd.get(), digest.get());
-    if (!measure.ok()) {
-        return measure.error();
-    }
-
     return {};
 }
 
@@ -303,11 +287,8 @@
     while (!ec && it != end) {
         if (it->is_regular_file()) {
             // Verify the file is in fs-verity
-            auto result = isFileInVerity(it->path());
-            if (!result.ok()) {
-                return result.error();
-            }
-            digests[it->path()] = *result;
+            auto result = OR_RETURN(measureFsVerity(it->path()));
+            digests[it->path()] = result;
         } else if (it->is_directory()) {
             // These are fine to ignore
         } else if (it->is_symlink()) {
@@ -344,7 +325,7 @@
                 return ErrnoError() << "Can't open " << path;
             }
 
-            auto verity_digest = isFileInVerity(fd);
+            auto verity_digest = measureFsVerity(fd);
             if (verity_digest.ok()) {
                 // The file is already in fs-verity. We need to make sure it was signed
                 // by CompOS, so we just check that it has the digest we expect.