summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaichi Hirono2017-03-22 02:41:46 -0500
committerDaichi Hirono2017-03-22 20:04:15 -0500
commit0bb22bd50ea7264684fa8c35b34fcc380e9d2cdc (patch)
treedc8ee89f3beba20ceda8e075554427c8709b3f37 /libappfuse
parentce009490fbf3fffc7aa2d1cd91b1485d6e98eaf8 (diff)
downloadplatform-system-core-0bb22bd50ea7264684fa8c35b34fcc380e9d2cdc.tar.gz
platform-system-core-0bb22bd50ea7264684fa8c35b34fcc380e9d2cdc.tar.xz
platform-system-core-0bb22bd50ea7264684fa8c35b34fcc380e9d2cdc.zip
Add FuseMessage::WriteWithBody function
The funciton is going to be used to write FUSE header with external body. Bug: 35229514 Test: libappfuse_tests Change-Id: I303022b555deca960b8e08f26140a5ef10133efe
Diffstat (limited to 'libappfuse')
-rw-r--r--libappfuse/FuseBuffer.cc64
-rw-r--r--libappfuse/include/libappfuse/FuseBuffer.h44
2 files changed, 66 insertions, 42 deletions
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index 13cfc88ec..5bc549743 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -24,6 +24,7 @@
24#include <type_traits> 24#include <type_traits>
25 25
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/uio.h>
27 28
28#include <android-base/file.h> 29#include <android-base/file.h>
29#include <android-base/logging.h> 30#include <android-base/logging.h>
@@ -34,9 +35,9 @@ namespace fuse {
34namespace { 35namespace {
35 36
36template <typename T> 37template <typename T>
37bool CheckHeaderLength(const FuseMessage<T>* self, const char* name) { 38bool CheckHeaderLength(const FuseMessage<T>* self, const char* name, size_t max_size) {
38 const auto& header = static_cast<const T*>(self)->header; 39 const auto& header = static_cast<const T*>(self)->header;
39 if (header.len >= sizeof(header) && header.len <= sizeof(T)) { 40 if (header.len >= sizeof(header) && header.len <= max_size) {
40 return true; 41 return true;
41 } else { 42 } else {
42 LOG(ERROR) << "Invalid header length is found in " << name << ": " << header.len; 43 LOG(ERROR) << "Invalid header length is found in " << name << ": " << header.len;
@@ -68,7 +69,7 @@ ResultOrAgain ReadInternal(FuseMessage<T>* self, int fd, int sockflag) {
68 return ResultOrAgain::kFailure; 69 return ResultOrAgain::kFailure;
69 } 70 }
70 71
71 if (!CheckHeaderLength<T>(self, "Read")) { 72 if (!CheckHeaderLength<T>(self, "Read", sizeof(T))) {
72 return ResultOrAgain::kFailure; 73 return ResultOrAgain::kFailure;
73 } 74 }
74 75
@@ -81,15 +82,26 @@ ResultOrAgain ReadInternal(FuseMessage<T>* self, int fd, int sockflag) {
81} 82}
82 83
83template <typename T> 84template <typename T>
84ResultOrAgain WriteInternal(const FuseMessage<T>* self, int fd, int sockflag) { 85ResultOrAgain WriteInternal(const FuseMessage<T>* self, int fd, int sockflag, const void* data,
85 if (!CheckHeaderLength<T>(self, "Write")) { 86 size_t max_size) {
87 if (!CheckHeaderLength<T>(self, "Write", max_size)) {
86 return ResultOrAgain::kFailure; 88 return ResultOrAgain::kFailure;
87 } 89 }
88 90
89 const char* const buf = reinterpret_cast<const char*>(self); 91 const char* const buf = reinterpret_cast<const char*>(self);
90 const auto& header = static_cast<const T*>(self)->header; 92 const auto& header = static_cast<const T*>(self)->header;
91 const int result = sockflag ? TEMP_FAILURE_RETRY(send(fd, buf, header.len, sockflag)) 93
92 : TEMP_FAILURE_RETRY(write(fd, buf, header.len)); 94 int result;
95 if (sockflag) {
96 CHECK(data == nullptr);
97 result = TEMP_FAILURE_RETRY(send(fd, buf, header.len, sockflag));
98 } else if (data) {
99 const struct iovec vec[] = {{const_cast<char*>(buf), sizeof(header)},
100 {const_cast<void*>(data), header.len - sizeof(header)}};
101 result = TEMP_FAILURE_RETRY(writev(fd, vec, arraysize(vec)));
102 } else {
103 result = TEMP_FAILURE_RETRY(write(fd, buf, header.len));
104 }
93 105
94 if (result == -1) { 106 if (result == -1) {
95 if (errno == EAGAIN) { 107 if (errno == EAGAIN) {
@@ -143,16 +155,19 @@ ResultOrAgain FuseMessage<T>::ReadOrAgain(int fd) {
143 155
144template <typename T> 156template <typename T>
145bool FuseMessage<T>::Write(int fd) const { 157bool FuseMessage<T>::Write(int fd) const {
146 return WriteInternal(this, fd, 0) == ResultOrAgain::kSuccess; 158 return WriteInternal(this, fd, 0, nullptr, sizeof(T)) == ResultOrAgain::kSuccess;
147} 159}
148 160
149template <typename T> 161template <typename T>
150ResultOrAgain FuseMessage<T>::WriteOrAgain(int fd) const { 162bool FuseMessage<T>::WriteWithBody(int fd, size_t max_size, const void* data) const {
151 return WriteInternal(this, fd, MSG_DONTWAIT); 163 CHECK(data != nullptr);
164 return WriteInternal<T>(this, fd, 0, data, max_size) == ResultOrAgain::kSuccess;
152} 165}
153 166
154template class FuseMessage<FuseRequest>; 167template <typename T>
155template class FuseMessage<FuseResponse>; 168ResultOrAgain FuseMessage<T>::WriteOrAgain(int fd) const {
169 return WriteInternal(this, fd, MSG_DONTWAIT, nullptr, sizeof(T));
170}
156 171
157void FuseRequest::Reset( 172void FuseRequest::Reset(
158 uint32_t data_length, uint32_t opcode, uint64_t unique) { 173 uint32_t data_length, uint32_t opcode, uint64_t unique) {
@@ -162,17 +177,18 @@ void FuseRequest::Reset(
162 header.unique = unique; 177 header.unique = unique;
163} 178}
164 179
165void FuseResponse::ResetHeader( 180template <size_t N>
166 uint32_t data_length, int32_t error, uint64_t unique) { 181void FuseResponseBase<N>::ResetHeader(uint32_t data_length, int32_t error, uint64_t unique) {
167 CHECK_LE(error, 0) << "error should be zero or negative."; 182 CHECK_LE(error, 0) << "error should be zero or negative.";
168 header.len = sizeof(fuse_out_header) + data_length; 183 header.len = sizeof(fuse_out_header) + data_length;
169 header.error = error; 184 header.error = error;
170 header.unique = unique; 185 header.unique = unique;
171} 186}
172 187
173void FuseResponse::Reset(uint32_t data_length, int32_t error, uint64_t unique) { 188template <size_t N>
174 memset(this, 0, sizeof(fuse_out_header) + data_length); 189void FuseResponseBase<N>::Reset(uint32_t data_length, int32_t error, uint64_t unique) {
175 ResetHeader(data_length, error, unique); 190 memset(this, 0, sizeof(fuse_out_header) + data_length);
191 ResetHeader(data_length, error, unique);
176} 192}
177 193
178void FuseBuffer::HandleInit() { 194void FuseBuffer::HandleInit() {
@@ -222,5 +238,11 @@ void FuseBuffer::HandleNotImpl() {
222 response.Reset(0, -ENOSYS, unique); 238 response.Reset(0, -ENOSYS, unique);
223} 239}
224 240
241template class FuseMessage<FuseRequest>;
242template class FuseMessage<FuseResponse>;
243template class FuseMessage<FuseSimpleResponse>;
244template struct FuseResponseBase<0u>;
245template struct FuseResponseBase<kFuseMaxRead>;
246
225} // namespace fuse 247} // namespace fuse
226} // namespace android 248} // namespace android
diff --git a/libappfuse/include/libappfuse/FuseBuffer.h b/libappfuse/include/libappfuse/FuseBuffer.h
index fbb05d633..7a70bf3b4 100644
--- a/libappfuse/include/libappfuse/FuseBuffer.h
+++ b/libappfuse/include/libappfuse/FuseBuffer.h
@@ -43,11 +43,9 @@ class FuseMessage {
43 public: 43 public:
44 bool Read(int fd); 44 bool Read(int fd);
45 bool Write(int fd) const; 45 bool Write(int fd) const;
46 bool WriteWithBody(int fd, size_t max_size, const void* data) const;
46 ResultOrAgain ReadOrAgain(int fd); 47 ResultOrAgain ReadOrAgain(int fd);
47 ResultOrAgain WriteOrAgain(int fd) const; 48 ResultOrAgain WriteOrAgain(int fd) const;
48
49private:
50 bool CheckHeaderLength(const char* name) const;
51}; 49};
52 50
53// FuseRequest represents file operation requests from /dev/fuse. It starts 51// FuseRequest represents file operation requests from /dev/fuse. It starts
@@ -74,26 +72,30 @@ struct FuseRequest : public FuseMessage<FuseRequest> {
74 72
75// FuseResponse represents file operation responses to /dev/fuse. It starts 73// FuseResponse represents file operation responses to /dev/fuse. It starts
76// from fuse_out_header. The body layout depends on the operation code. 74// from fuse_out_header. The body layout depends on the operation code.
77struct FuseResponse : public FuseMessage<FuseResponse> { 75template <size_t N>
78 fuse_out_header header; 76struct FuseResponseBase : public FuseMessage<FuseResponseBase<N>> {
79 union { 77 fuse_out_header header;
80 // for FUSE_INIT 78 union {
81 fuse_init_out init_out; 79 // for FUSE_INIT
82 // for FUSE_LOOKUP 80 fuse_init_out init_out;
83 fuse_entry_out entry_out; 81 // for FUSE_LOOKUP
84 // for FUSE_GETATTR 82 fuse_entry_out entry_out;
85 fuse_attr_out attr_out; 83 // for FUSE_GETATTR
86 // for FUSE_OPEN 84 fuse_attr_out attr_out;
87 fuse_open_out open_out; 85 // for FUSE_OPEN
88 // for FUSE_READ 86 fuse_open_out open_out;
89 char read_data[kFuseMaxRead]; 87 // for FUSE_READ
90 // for FUSE_WRITE 88 char read_data[N];
91 fuse_write_out write_out; 89 // for FUSE_WRITE
92 }; 90 fuse_write_out write_out;
93 void Reset(uint32_t data_length, int32_t error, uint64_t unique); 91 };
94 void ResetHeader(uint32_t data_length, int32_t error, uint64_t unique); 92 void Reset(uint32_t data_length, int32_t error, uint64_t unique);
93 void ResetHeader(uint32_t data_length, int32_t error, uint64_t unique);
95}; 94};
96 95
96using FuseResponse = FuseResponseBase<kFuseMaxRead>;
97using FuseSimpleResponse = FuseResponseBase<0u>;
98
97// To reduce memory usage, FuseBuffer shares the memory region for request and 99// To reduce memory usage, FuseBuffer shares the memory region for request and
98// response. 100// response.
99union FuseBuffer final { 101union FuseBuffer final {