Add static assert to check if FuseBuffer is standard layout union.
Bug: 32260320
Test: libappfuse_test
Change-Id: I6430c11fdeb2405996410c97044b4260c25209b8
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index ca47aa8..74fe756 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <algorithm>
+#include <type_traits>
#include <android-base/logging.h>
#include <android-base/macros.h>
@@ -28,9 +29,14 @@
namespace android {
namespace fuse {
-template <typename T, typename Header>
-bool FuseMessage<T, Header>::CheckHeaderLength() const {
- if (sizeof(Header) <= header.len && header.len <= sizeof(T)) {
+static_assert(
+ std::is_standard_layout<FuseBuffer>::value,
+ "FuseBuffer must be standard layout union.");
+
+template <typename T>
+bool FuseMessage<T>::CheckHeaderLength() const {
+ const auto& header = static_cast<const T*>(this)->header;
+ if (sizeof(header) <= header.len && header.len <= sizeof(T)) {
return true;
} else {
LOG(ERROR) << "Packet size is invalid=" << header.len;
@@ -38,9 +44,10 @@
}
}
-template <typename T, typename Header>
-bool FuseMessage<T, Header>::CheckResult(
+template <typename T>
+bool FuseMessage<T>::CheckResult(
int result, const char* operation_name) const {
+ const auto& header = static_cast<const T*>(this)->header;
if (result >= 0 && static_cast<uint32_t>(result) == header.len) {
return true;
} else {
@@ -51,14 +58,15 @@
}
}
-template <typename T, typename Header>
-bool FuseMessage<T, Header>::Read(int fd) {
+template <typename T>
+bool FuseMessage<T>::Read(int fd) {
const ssize_t result = TEMP_FAILURE_RETRY(::read(fd, this, sizeof(T)));
return CheckHeaderLength() && CheckResult(result, "read");
}
-template <typename T, typename Header>
-bool FuseMessage<T, Header>::Write(int fd) const {
+template <typename T>
+bool FuseMessage<T>::Write(int fd) const {
+ const auto& header = static_cast<const T*>(this)->header;
if (!CheckHeaderLength()) {
return false;
}
@@ -66,8 +74,8 @@
return CheckResult(result, "write");
}
-template struct FuseMessage<FuseRequest, fuse_in_header>;
-template struct FuseMessage<FuseResponse, fuse_out_header>;
+template class FuseMessage<FuseRequest>;
+template class FuseMessage<FuseResponse>;
void FuseRequest::Reset(
uint32_t data_length, uint32_t opcode, uint64_t unique) {