diff options
author | Daichi Hirono | 2016-11-07 19:17:51 -0600 |
---|---|---|
committer | Daichi Hirono | 2016-11-14 18:47:31 -0600 |
commit | a0aecda12b9a76aa15a8c5175e15538574a05af7 (patch) | |
tree | ac1e8eda1f03a8922445ae13d6d7a4173158c4ec /libappfuse | |
parent | b5ce6f02dd11b42c03884dd9531c6c8a80bcecda (diff) | |
download | platform-system-core-a0aecda12b9a76aa15a8c5175e15538574a05af7.tar.gz platform-system-core-a0aecda12b9a76aa15a8c5175e15538574a05af7.tar.xz platform-system-core-a0aecda12b9a76aa15a8c5175e15538574a05af7.zip |
Add FuseAppLoop to libappfuse.
The class is used at the app side (StorageManager) to parse FUSE
commands.
Bug: 32260320
Test: libappfuse_test
Change-Id: I1ae2904d3290a041f1efbf8fc10ba032eda5449c
Diffstat (limited to 'libappfuse')
-rw-r--r-- | libappfuse/Android.bp | 12 | ||||
-rw-r--r-- | libappfuse/FuseAppLoop.cc | 221 | ||||
-rw-r--r-- | libappfuse/FuseBridgeLoop.cc | 25 | ||||
-rw-r--r-- | libappfuse/FuseBuffer.cc | 12 | ||||
-rw-r--r-- | libappfuse/include/libappfuse/FuseAppLoop.h | 44 | ||||
-rw-r--r-- | libappfuse/include/libappfuse/FuseBridgeLoop.h | 14 | ||||
-rw-r--r-- | libappfuse/include/libappfuse/FuseBuffer.h | 39 | ||||
-rw-r--r-- | libappfuse/tests/FuseAppLoopTest.cc | 307 | ||||
-rw-r--r-- | libappfuse/tests/FuseBridgeLoopTest.cc | 47 | ||||
-rw-r--r-- | libappfuse/tests/FuseBufferTest.cc | 6 |
10 files changed, 678 insertions, 49 deletions
diff --git a/libappfuse/Android.bp b/libappfuse/Android.bp index 8b4615405..f729faf73 100644 --- a/libappfuse/Android.bp +++ b/libappfuse/Android.bp | |||
@@ -15,12 +15,20 @@ cc_library_shared { | |||
15 | name: "libappfuse", | 15 | name: "libappfuse", |
16 | defaults: ["libappfuse_defaults"], | 16 | defaults: ["libappfuse_defaults"], |
17 | export_include_dirs: ["include"], | 17 | export_include_dirs: ["include"], |
18 | srcs: ["FuseBuffer.cc", "FuseBridgeLoop.cc"] | 18 | srcs: [ |
19 | "FuseAppLoop.cc", | ||
20 | "FuseBuffer.cc", | ||
21 | "FuseBridgeLoop.cc", | ||
22 | ] | ||
19 | } | 23 | } |
20 | 24 | ||
21 | cc_test { | 25 | cc_test { |
22 | name: "libappfuse_test", | 26 | name: "libappfuse_test", |
23 | defaults: ["libappfuse_defaults"], | 27 | defaults: ["libappfuse_defaults"], |
24 | shared_libs: ["libappfuse"], | 28 | shared_libs: ["libappfuse"], |
25 | srcs: ["tests/FuseBridgeLoopTest.cc", "tests/FuseBufferTest.cc"] | 29 | srcs: [ |
30 | "tests/FuseAppLoopTest.cc", | ||
31 | "tests/FuseBridgeLoopTest.cc", | ||
32 | "tests/FuseBufferTest.cc", | ||
33 | ] | ||
26 | } | 34 | } |
diff --git a/libappfuse/FuseAppLoop.cc b/libappfuse/FuseAppLoop.cc new file mode 100644 index 000000000..a31880e41 --- /dev/null +++ b/libappfuse/FuseAppLoop.cc | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specic language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "libappfuse/FuseAppLoop.h" | ||
18 | |||
19 | #include <sys/stat.h> | ||
20 | |||
21 | #include <android-base/logging.h> | ||
22 | #include <android-base/unique_fd.h> | ||
23 | |||
24 | namespace android { | ||
25 | namespace fuse { | ||
26 | |||
27 | namespace { | ||
28 | |||
29 | void HandleLookUp(FuseBuffer* buffer, FuseAppLoopCallback* callback) { | ||
30 | // AppFuse does not support directory structure now. | ||
31 | // It can lookup only files under the mount point. | ||
32 | if (buffer->request.header.nodeid != FUSE_ROOT_ID) { | ||
33 | LOG(ERROR) << "Nodeid is not FUSE_ROOT_ID."; | ||
34 | buffer->response.Reset(0, -ENOENT, buffer->request.header.unique); | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | // Ensure that the filename ends with 0. | ||
39 | const size_t filename_length = | ||
40 | buffer->request.header.len - sizeof(fuse_in_header); | ||
41 | if (buffer->request.lookup_name[filename_length - 1] != 0) { | ||
42 | LOG(ERROR) << "File name does not end with 0."; | ||
43 | buffer->response.Reset(0, -ENOENT, buffer->request.header.unique); | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | const uint64_t inode = | ||
48 | static_cast<uint64_t>(atol(buffer->request.lookup_name)); | ||
49 | if (inode == 0 || inode == LONG_MAX) { | ||
50 | LOG(ERROR) << "Invalid filename"; | ||
51 | buffer->response.Reset(0, -ENOENT, buffer->request.header.unique); | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | const int64_t size = callback->OnGetSize(inode); | ||
56 | if (size < 0) { | ||
57 | buffer->response.Reset(0, size, buffer->request.header.unique); | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | buffer->response.Reset(sizeof(fuse_entry_out), 0, | ||
62 | buffer->request.header.unique); | ||
63 | buffer->response.entry_out.nodeid = inode; | ||
64 | buffer->response.entry_out.attr_valid = 10; | ||
65 | buffer->response.entry_out.entry_valid = 10; | ||
66 | buffer->response.entry_out.attr.ino = inode; | ||
67 | buffer->response.entry_out.attr.mode = S_IFREG | 0777; | ||
68 | buffer->response.entry_out.attr.size = size; | ||
69 | } | ||
70 | |||
71 | void HandleGetAttr(FuseBuffer* buffer, FuseAppLoopCallback* callback) { | ||
72 | const uint64_t nodeid = buffer->request.header.nodeid; | ||
73 | int64_t size; | ||
74 | uint32_t mode; | ||
75 | if (nodeid == FUSE_ROOT_ID) { | ||
76 | size = 0; | ||
77 | mode = S_IFDIR | 0777; | ||
78 | } else { | ||
79 | size = callback->OnGetSize(buffer->request.header.nodeid); | ||
80 | if (size < 0) { | ||
81 | buffer->response.Reset(0, size, buffer->request.header.unique); | ||
82 | return; | ||
83 | } | ||
84 | mode = S_IFREG | 0777; | ||
85 | } | ||
86 | |||
87 | buffer->response.Reset(sizeof(fuse_attr_out), 0, | ||
88 | buffer->request.header.unique); | ||
89 | buffer->response.attr_out.attr_valid = 10; | ||
90 | buffer->response.attr_out.attr.ino = nodeid; | ||
91 | buffer->response.attr_out.attr.mode = mode; | ||
92 | buffer->response.attr_out.attr.size = size; | ||
93 | } | ||
94 | |||
95 | void HandleOpen(FuseBuffer* buffer, FuseAppLoopCallback* callback) { | ||
96 | const int32_t file_handle = callback->OnOpen(buffer->request.header.nodeid); | ||
97 | if (file_handle < 0) { | ||
98 | buffer->response.Reset(0, file_handle, buffer->request.header.unique); | ||
99 | return; | ||
100 | } | ||
101 | buffer->response.Reset(sizeof(fuse_open_out), kFuseSuccess, | ||
102 | buffer->request.header.unique); | ||
103 | buffer->response.open_out.fh = file_handle; | ||
104 | } | ||
105 | |||
106 | void HandleFsync(FuseBuffer* buffer, FuseAppLoopCallback* callback) { | ||
107 | buffer->response.Reset(0, callback->OnFsync(buffer->request.header.nodeid), | ||
108 | buffer->request.header.unique); | ||
109 | } | ||
110 | |||
111 | void HandleRelease(FuseBuffer* buffer, FuseAppLoopCallback* callback) { | ||
112 | buffer->response.Reset(0, callback->OnRelease(buffer->request.header.nodeid), | ||
113 | buffer->request.header.unique); | ||
114 | } | ||
115 | |||
116 | void HandleRead(FuseBuffer* buffer, FuseAppLoopCallback* callback) { | ||
117 | const uint64_t unique = buffer->request.header.unique; | ||
118 | const uint64_t nodeid = buffer->request.header.nodeid; | ||
119 | const uint64_t offset = buffer->request.read_in.offset; | ||
120 | const uint32_t size = buffer->request.read_in.size; | ||
121 | |||
122 | if (size > kFuseMaxRead) { | ||
123 | buffer->response.Reset(0, -EINVAL, buffer->request.header.unique); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | const int32_t read_size = callback->OnRead(nodeid, offset, size, | ||
128 | buffer->response.read_data); | ||
129 | if (read_size < 0) { | ||
130 | buffer->response.Reset(0, read_size, buffer->request.header.unique); | ||
131 | return; | ||
132 | } | ||
133 | |||
134 | buffer->response.ResetHeader(read_size, kFuseSuccess, unique); | ||
135 | } | ||
136 | |||
137 | void HandleWrite(FuseBuffer* buffer, FuseAppLoopCallback* callback) { | ||
138 | const uint64_t unique = buffer->request.header.unique; | ||
139 | const uint64_t nodeid = buffer->request.header.nodeid; | ||
140 | const uint64_t offset = buffer->request.write_in.offset; | ||
141 | const uint32_t size = buffer->request.write_in.size; | ||
142 | |||
143 | if (size > kFuseMaxWrite) { | ||
144 | buffer->response.Reset(0, -EINVAL, buffer->request.header.unique); | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | const int32_t write_size = callback->OnWrite(nodeid, offset, size, | ||
149 | buffer->request.write_data); | ||
150 | if (write_size < 0) { | ||
151 | buffer->response.Reset(0, write_size, buffer->request.header.unique); | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | buffer->response.Reset(sizeof(fuse_write_out), kFuseSuccess, unique); | ||
156 | buffer->response.write_out.size = write_size; | ||
157 | } | ||
158 | |||
159 | } // namespace | ||
160 | |||
161 | bool StartFuseAppLoop(int raw_fd, FuseAppLoopCallback* callback) { | ||
162 | base::unique_fd fd(raw_fd); | ||
163 | FuseBuffer buffer; | ||
164 | |||
165 | LOG(DEBUG) << "Start fuse loop."; | ||
166 | while (callback->IsActive()) { | ||
167 | if (!buffer.request.Read(fd)) { | ||
168 | return false; | ||
169 | } | ||
170 | |||
171 | const uint32_t opcode = buffer.request.header.opcode; | ||
172 | LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode; | ||
173 | switch (opcode) { | ||
174 | case FUSE_FORGET: | ||
175 | // Do not reply to FUSE_FORGET. | ||
176 | continue; | ||
177 | |||
178 | case FUSE_LOOKUP: | ||
179 | HandleLookUp(&buffer, callback); | ||
180 | break; | ||
181 | |||
182 | case FUSE_GETATTR: | ||
183 | HandleGetAttr(&buffer, callback); | ||
184 | break; | ||
185 | |||
186 | case FUSE_OPEN: | ||
187 | HandleOpen(&buffer, callback); | ||
188 | break; | ||
189 | |||
190 | case FUSE_READ: | ||
191 | HandleRead(&buffer, callback); | ||
192 | break; | ||
193 | |||
194 | case FUSE_WRITE: | ||
195 | HandleWrite(&buffer, callback); | ||
196 | break; | ||
197 | |||
198 | case FUSE_RELEASE: | ||
199 | HandleRelease(&buffer, callback); | ||
200 | break; | ||
201 | |||
202 | case FUSE_FSYNC: | ||
203 | HandleFsync(&buffer, callback); | ||
204 | break; | ||
205 | |||
206 | default: | ||
207 | buffer.HandleNotImpl(); | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | if (!buffer.response.Write(fd)) { | ||
212 | LOG(ERROR) << "Failed to write a response to the device."; | ||
213 | return false; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | return true; | ||
218 | } | ||
219 | |||
220 | } // namespace fuse | ||
221 | } // namespace android | ||
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc index 332556dd1..acb963cfc 100644 --- a/libappfuse/FuseBridgeLoop.cc +++ b/libappfuse/FuseBridgeLoop.cc | |||
@@ -25,14 +25,15 @@ bool FuseBridgeLoop::Start( | |||
25 | int raw_dev_fd, int raw_proxy_fd, FuseBridgeLoop::Callback* callback) { | 25 | int raw_dev_fd, int raw_proxy_fd, FuseBridgeLoop::Callback* callback) { |
26 | base::unique_fd dev_fd(raw_dev_fd); | 26 | base::unique_fd dev_fd(raw_dev_fd); |
27 | base::unique_fd proxy_fd(raw_proxy_fd); | 27 | base::unique_fd proxy_fd(raw_proxy_fd); |
28 | fuse::FuseBuffer buffer; | ||
28 | 29 | ||
29 | LOG(DEBUG) << "Start fuse loop."; | 30 | LOG(DEBUG) << "Start fuse loop."; |
30 | while (true) { | 31 | while (true) { |
31 | if (!buffer_.request.Read(dev_fd)) { | 32 | if (!buffer.request.Read(dev_fd)) { |
32 | return false; | 33 | return false; |
33 | } | 34 | } |
34 | 35 | ||
35 | const uint32_t opcode = buffer_.request.header.opcode; | 36 | const uint32_t opcode = buffer.request.header.opcode; |
36 | LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode; | 37 | LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode; |
37 | switch (opcode) { | 38 | switch (opcode) { |
38 | case FUSE_FORGET: | 39 | case FUSE_FORGET: |
@@ -45,27 +46,27 @@ bool FuseBridgeLoop::Start( | |||
45 | case FUSE_READ: | 46 | case FUSE_READ: |
46 | case FUSE_WRITE: | 47 | case FUSE_WRITE: |
47 | case FUSE_RELEASE: | 48 | case FUSE_RELEASE: |
48 | case FUSE_FLUSH: | 49 | case FUSE_FSYNC: |
49 | if (!buffer_.request.Write(proxy_fd)) { | 50 | if (!buffer.request.Write(proxy_fd)) { |
50 | LOG(ERROR) << "Failed to write a request to the proxy."; | 51 | LOG(ERROR) << "Failed to write a request to the proxy."; |
51 | return false; | 52 | return false; |
52 | } | 53 | } |
53 | if (!buffer_.response.Read(proxy_fd)) { | 54 | if (!buffer.response.Read(proxy_fd)) { |
54 | LOG(ERROR) << "Failed to read a response from the proxy."; | 55 | LOG(ERROR) << "Failed to read a response from the proxy."; |
55 | return false; | 56 | return false; |
56 | } | 57 | } |
57 | break; | 58 | break; |
58 | 59 | ||
59 | case FUSE_INIT: | 60 | case FUSE_INIT: |
60 | buffer_.HandleInit(); | 61 | buffer.HandleInit(); |
61 | break; | 62 | break; |
62 | 63 | ||
63 | default: | 64 | default: |
64 | buffer_.HandleNotImpl(); | 65 | buffer.HandleNotImpl(); |
65 | break; | 66 | break; |
66 | } | 67 | } |
67 | 68 | ||
68 | if (!buffer_.response.Write(dev_fd)) { | 69 | if (!buffer.response.Write(dev_fd)) { |
69 | LOG(ERROR) << "Failed to write a response to the device."; | 70 | LOG(ERROR) << "Failed to write a response to the device."; |
70 | return false; | 71 | return false; |
71 | } | 72 | } |
@@ -76,4 +77,12 @@ bool FuseBridgeLoop::Start( | |||
76 | } | 77 | } |
77 | } | 78 | } |
78 | 79 | ||
80 | namespace fuse { | ||
81 | |||
82 | bool StartFuseBridgeLoop( | ||
83 | int raw_dev_fd, int raw_proxy_fd, FuseBridgeLoopCallback* callback) { | ||
84 | return FuseBridgeLoop().Start(raw_dev_fd, raw_proxy_fd, callback); | ||
85 | } | ||
86 | |||
87 | } // namespace fuse | ||
79 | } // namespace android | 88 | } // namespace android |
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc index 45280a5cf..ca47aa8c7 100644 --- a/libappfuse/FuseBuffer.cc +++ b/libappfuse/FuseBuffer.cc | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <android-base/macros.h> | 26 | #include <android-base/macros.h> |
27 | 27 | ||
28 | namespace android { | 28 | namespace android { |
29 | namespace fuse { | ||
29 | 30 | ||
30 | template <typename T, typename Header> | 31 | template <typename T, typename Header> |
31 | bool FuseMessage<T, Header>::CheckHeaderLength() const { | 32 | bool FuseMessage<T, Header>::CheckHeaderLength() const { |
@@ -44,7 +45,7 @@ bool FuseMessage<T, Header>::CheckResult( | |||
44 | return true; | 45 | return true; |
45 | } else { | 46 | } else { |
46 | PLOG(ERROR) << "Failed to " << operation_name | 47 | PLOG(ERROR) << "Failed to " << operation_name |
47 | << " a packet from FD. result=" << result << " header.len=" | 48 | << " a packet. result=" << result << " header.len=" |
48 | << header.len; | 49 | << header.len; |
49 | return false; | 50 | return false; |
50 | } | 51 | } |
@@ -68,6 +69,14 @@ bool FuseMessage<T, Header>::Write(int fd) const { | |||
68 | template struct FuseMessage<FuseRequest, fuse_in_header>; | 69 | template struct FuseMessage<FuseRequest, fuse_in_header>; |
69 | template struct FuseMessage<FuseResponse, fuse_out_header>; | 70 | template struct FuseMessage<FuseResponse, fuse_out_header>; |
70 | 71 | ||
72 | void FuseRequest::Reset( | ||
73 | uint32_t data_length, uint32_t opcode, uint64_t unique) { | ||
74 | memset(this, 0, sizeof(fuse_in_header) + data_length); | ||
75 | header.len = sizeof(fuse_in_header) + data_length; | ||
76 | header.opcode = opcode; | ||
77 | header.unique = unique; | ||
78 | } | ||
79 | |||
71 | void FuseResponse::ResetHeader( | 80 | void FuseResponse::ResetHeader( |
72 | uint32_t data_length, int32_t error, uint64_t unique) { | 81 | uint32_t data_length, int32_t error, uint64_t unique) { |
73 | CHECK_LE(error, 0) << "error should be zero or negative."; | 82 | CHECK_LE(error, 0) << "error should be zero or negative."; |
@@ -133,4 +142,5 @@ void FuseBuffer::HandleNotImpl() { | |||
133 | response.Reset(0, -ENOSYS, unique); | 142 | response.Reset(0, -ENOSYS, unique); |
134 | } | 143 | } |
135 | 144 | ||
145 | } // namespace fuse | ||
136 | } // namespace android | 146 | } // namespace android |
diff --git a/libappfuse/include/libappfuse/FuseAppLoop.h b/libappfuse/include/libappfuse/FuseAppLoop.h new file mode 100644 index 000000000..c3edfcc32 --- /dev/null +++ b/libappfuse/include/libappfuse/FuseAppLoop.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specic language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef ANDROID_LIBAPPFUSE_FUSEAPPLOOP_H_ | ||
18 | #define ANDROID_LIBAPPFUSE_FUSEAPPLOOP_H_ | ||
19 | |||
20 | #include "libappfuse/FuseBuffer.h" | ||
21 | |||
22 | namespace android { | ||
23 | namespace fuse { | ||
24 | |||
25 | class FuseAppLoopCallback { | ||
26 | public: | ||
27 | virtual bool IsActive() = 0; | ||
28 | virtual int64_t OnGetSize(uint64_t inode) = 0; | ||
29 | virtual int32_t OnFsync(uint64_t inode) = 0; | ||
30 | virtual int32_t OnWrite( | ||
31 | uint64_t inode, uint64_t offset, uint32_t size, const void* data) = 0; | ||
32 | virtual int32_t OnRead( | ||
33 | uint64_t inode, uint64_t offset, uint32_t size, void* data) = 0; | ||
34 | virtual int32_t OnOpen(uint64_t inode) = 0; | ||
35 | virtual int32_t OnRelease(uint64_t inode) = 0; | ||
36 | virtual ~FuseAppLoopCallback() = default; | ||
37 | }; | ||
38 | |||
39 | bool StartFuseAppLoop(int fd, FuseAppLoopCallback* callback); | ||
40 | |||
41 | } // namespace fuse | ||
42 | } // namespace android | ||
43 | |||
44 | #endif // ANDROID_LIBAPPFUSE_FUSEAPPLOOP_H_ | ||
diff --git a/libappfuse/include/libappfuse/FuseBridgeLoop.h b/libappfuse/include/libappfuse/FuseBridgeLoop.h index 200653252..38043bce7 100644 --- a/libappfuse/include/libappfuse/FuseBridgeLoop.h +++ b/libappfuse/include/libappfuse/FuseBridgeLoop.h | |||
@@ -21,7 +21,9 @@ | |||
21 | 21 | ||
22 | namespace android { | 22 | namespace android { |
23 | 23 | ||
24 | class FuseBridgeLoop { | 24 | // TODO: Remove the class after switching to StartFuseBridgeLoop in the |
25 | // framework code. | ||
26 | class FuseBridgeLoop final { | ||
25 | public: | 27 | public: |
26 | class Callback { | 28 | class Callback { |
27 | public: | 29 | public: |
@@ -30,11 +32,15 @@ class FuseBridgeLoop { | |||
30 | }; | 32 | }; |
31 | 33 | ||
32 | bool Start(int dev_fd, int proxy_fd, Callback* callback); | 34 | bool Start(int dev_fd, int proxy_fd, Callback* callback); |
33 | |||
34 | private: | ||
35 | FuseBuffer buffer_; | ||
36 | }; | 35 | }; |
37 | 36 | ||
37 | namespace fuse { | ||
38 | |||
39 | class FuseBridgeLoopCallback : public FuseBridgeLoop::Callback {}; | ||
40 | bool StartFuseBridgeLoop( | ||
41 | int dev_fd, int proxy_fd, FuseBridgeLoopCallback* callback); | ||
42 | |||
43 | } // namespace fuse | ||
38 | } // namespace android | 44 | } // namespace android |
39 | 45 | ||
40 | #endif // ANDROID_LIBAPPFUSE_FUSEBRIDGELOOP_H_ | 46 | #endif // ANDROID_LIBAPPFUSE_FUSEBRIDGELOOP_H_ |
diff --git a/libappfuse/include/libappfuse/FuseBuffer.h b/libappfuse/include/libappfuse/FuseBuffer.h index 071b77715..1464142c4 100644 --- a/libappfuse/include/libappfuse/FuseBuffer.h +++ b/libappfuse/include/libappfuse/FuseBuffer.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/fuse.h> | 20 | #include <linux/fuse.h> |
21 | 21 | ||
22 | namespace android { | 22 | namespace android { |
23 | namespace fuse { | ||
23 | 24 | ||
24 | // The numbers came from sdcard.c. | 25 | // The numbers came from sdcard.c. |
25 | // Maximum number of bytes to write/read in one request/one reply. | 26 | // Maximum number of bytes to write/read in one request/one reply. |
@@ -37,33 +38,51 @@ struct FuseMessage { | |||
37 | bool CheckResult(int result, const char* operation_name) const; | 38 | bool CheckResult(int result, const char* operation_name) const; |
38 | }; | 39 | }; |
39 | 40 | ||
40 | struct FuseRequest : public FuseMessage<FuseRequest, fuse_in_header> { | 41 | // FuseRequest represents file operation requests from /dev/fuse. It starts |
42 | // from fuse_in_header. The body layout depends on the operation code. | ||
43 | struct FuseRequest final : public FuseMessage<FuseRequest, fuse_in_header> { | ||
41 | union { | 44 | union { |
45 | // for FUSE_WRITE | ||
42 | struct { | 46 | struct { |
43 | fuse_write_in write_in; | 47 | fuse_write_in write_in; |
44 | char write_data[kFuseMaxWrite]; | 48 | char write_data[kFuseMaxWrite]; |
45 | }; | 49 | }; |
50 | // for FUSE_OPEN | ||
46 | fuse_open_in open_in; | 51 | fuse_open_in open_in; |
52 | // for FUSE_INIT | ||
47 | fuse_init_in init_in; | 53 | fuse_init_in init_in; |
54 | // for FUSE_READ | ||
48 | fuse_read_in read_in; | 55 | fuse_read_in read_in; |
56 | // for FUSE_LOOKUP | ||
49 | char lookup_name[0]; | 57 | char lookup_name[0]; |
50 | }; | 58 | }; |
59 | void Reset(uint32_t data_length, uint32_t opcode, uint64_t unique); | ||
51 | }; | 60 | }; |
52 | 61 | ||
53 | struct FuseResponse : public FuseMessage<FuseResponse, fuse_out_header> { | 62 | // FuseResponse represents file operation responses to /dev/fuse. It starts |
63 | // from fuse_out_header. The body layout depends on the operation code. | ||
64 | struct FuseResponse final : public FuseMessage<FuseResponse, fuse_out_header> { | ||
54 | union { | 65 | union { |
66 | // for FUSE_INIT | ||
55 | fuse_init_out init_out; | 67 | fuse_init_out init_out; |
68 | // for FUSE_LOOKUP | ||
56 | fuse_entry_out entry_out; | 69 | fuse_entry_out entry_out; |
70 | // for FUSE_GETATTR | ||
57 | fuse_attr_out attr_out; | 71 | fuse_attr_out attr_out; |
72 | // for FUSE_OPEN | ||
58 | fuse_open_out open_out; | 73 | fuse_open_out open_out; |
74 | // for FUSE_READ | ||
59 | char read_data[kFuseMaxRead]; | 75 | char read_data[kFuseMaxRead]; |
76 | // for FUSE_WRITE | ||
60 | fuse_write_out write_out; | 77 | fuse_write_out write_out; |
61 | }; | 78 | }; |
62 | void Reset(uint32_t data_length, int32_t error, uint64_t unique); | 79 | void Reset(uint32_t data_length, int32_t error, uint64_t unique); |
63 | void ResetHeader(uint32_t data_length, int32_t error, uint64_t unique); | 80 | void ResetHeader(uint32_t data_length, int32_t error, uint64_t unique); |
64 | }; | 81 | }; |
65 | 82 | ||
66 | union FuseBuffer { | 83 | // To reduce memory usage, FuseBuffer shares the memory region for request and |
84 | // response. | ||
85 | union FuseBuffer final { | ||
67 | FuseRequest request; | 86 | FuseRequest request; |
68 | FuseResponse response; | 87 | FuseResponse response; |
69 | 88 | ||
@@ -71,19 +90,7 @@ union FuseBuffer { | |||
71 | void HandleNotImpl(); | 90 | void HandleNotImpl(); |
72 | }; | 91 | }; |
73 | 92 | ||
74 | class FuseProxyLoop { | 93 | } // namespace fuse |
75 | class IFuseProxyLoopCallback { | ||
76 | public: | ||
77 | virtual void OnMount() = 0; | ||
78 | virtual ~IFuseProxyLoopCallback() = default; | ||
79 | }; | ||
80 | |||
81 | bool Start(int dev_fd, int proxy_fd, IFuseProxyLoopCallback* callback); | ||
82 | |||
83 | private: | ||
84 | FuseBuffer buffer_; | ||
85 | }; | ||
86 | |||
87 | } // namespace android | 94 | } // namespace android |
88 | 95 | ||
89 | #endif // ANDROID_LIBAPPFUSE_FUSEBUFFER_H_ | 96 | #endif // ANDROID_LIBAPPFUSE_FUSEBUFFER_H_ |
diff --git a/libappfuse/tests/FuseAppLoopTest.cc b/libappfuse/tests/FuseAppLoopTest.cc new file mode 100644 index 000000000..25906cf1c --- /dev/null +++ b/libappfuse/tests/FuseAppLoopTest.cc | |||
@@ -0,0 +1,307 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specic language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "libappfuse/FuseAppLoop.h" | ||
18 | |||
19 | #include <sys/socket.h> | ||
20 | |||
21 | #include <android-base/logging.h> | ||
22 | #include <android-base/unique_fd.h> | ||
23 | #include <gtest/gtest.h> | ||
24 | #include <thread> | ||
25 | |||
26 | namespace android { | ||
27 | namespace fuse { | ||
28 | namespace { | ||
29 | |||
30 | constexpr unsigned int kTestFileSize = 1024; | ||
31 | |||
32 | struct CallbackRequest { | ||
33 | uint32_t code; | ||
34 | uint64_t inode; | ||
35 | }; | ||
36 | |||
37 | class Callback : public FuseAppLoopCallback { | ||
38 | public: | ||
39 | std::vector<CallbackRequest> requests; | ||
40 | |||
41 | bool IsActive() override { | ||
42 | return true; | ||
43 | } | ||
44 | |||
45 | int64_t OnGetSize(uint64_t inode) override { | ||
46 | if (inode == FUSE_ROOT_ID) { | ||
47 | return 0; | ||
48 | } else { | ||
49 | return kTestFileSize; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | int32_t OnFsync(uint64_t inode) override { | ||
54 | requests.push_back({ | ||
55 | .code = FUSE_FSYNC, | ||
56 | .inode = inode | ||
57 | }); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | int32_t OnWrite(uint64_t inode, | ||
62 | uint64_t offset ATTRIBUTE_UNUSED, | ||
63 | uint32_t size ATTRIBUTE_UNUSED, | ||
64 | const void* data ATTRIBUTE_UNUSED) override { | ||
65 | requests.push_back({ | ||
66 | .code = FUSE_WRITE, | ||
67 | .inode = inode | ||
68 | }); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | int32_t OnRead(uint64_t inode, | ||
73 | uint64_t offset ATTRIBUTE_UNUSED, | ||
74 | uint32_t size ATTRIBUTE_UNUSED, | ||
75 | void* data ATTRIBUTE_UNUSED) override { | ||
76 | requests.push_back({ | ||
77 | .code = FUSE_READ, | ||
78 | .inode = inode | ||
79 | }); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | int32_t OnOpen(uint64_t inode) override { | ||
84 | requests.push_back({ | ||
85 | .code = FUSE_OPEN, | ||
86 | .inode = inode | ||
87 | }); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | int32_t OnRelease(uint64_t inode) override { | ||
92 | requests.push_back({ | ||
93 | .code = FUSE_RELEASE, | ||
94 | .inode = inode | ||
95 | }); | ||
96 | return 0; | ||
97 | } | ||
98 | }; | ||
99 | |||
100 | class FuseAppLoopTest : public ::testing::Test { | ||
101 | private: | ||
102 | std::thread thread_; | ||
103 | |||
104 | protected: | ||
105 | base::unique_fd sockets_[2]; | ||
106 | Callback callback_; | ||
107 | FuseRequest request_; | ||
108 | FuseResponse response_; | ||
109 | |||
110 | void SetUp() override { | ||
111 | base::SetMinimumLogSeverity(base::VERBOSE); | ||
112 | int sockets[2]; | ||
113 | ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)); | ||
114 | sockets_[0].reset(sockets[0]); | ||
115 | sockets_[1].reset(sockets[1]); | ||
116 | thread_ = std::thread([this] { | ||
117 | StartFuseAppLoop(sockets_[1].release(), &callback_); | ||
118 | }); | ||
119 | } | ||
120 | |||
121 | void CheckCallback( | ||
122 | size_t data_size, uint32_t code, size_t expected_out_size) { | ||
123 | request_.Reset(data_size, code, 1); | ||
124 | request_.header.nodeid = 10; | ||
125 | |||
126 | ASSERT_TRUE(request_.Write(sockets_[0])); | ||
127 | ASSERT_TRUE(response_.Read(sockets_[0])); | ||
128 | |||
129 | Close(); | ||
130 | |||
131 | EXPECT_EQ(kFuseSuccess, response_.header.error); | ||
132 | EXPECT_EQ(sizeof(fuse_out_header) + expected_out_size, | ||
133 | response_.header.len); | ||
134 | EXPECT_EQ(1u, response_.header.unique); | ||
135 | |||
136 | ASSERT_EQ(1u, callback_.requests.size()); | ||
137 | EXPECT_EQ(code, callback_.requests[0].code); | ||
138 | EXPECT_EQ(10u, callback_.requests[0].inode); | ||
139 | } | ||
140 | |||
141 | void Close() { | ||
142 | sockets_[0].reset(); | ||
143 | sockets_[1].reset(); | ||
144 | if (thread_.joinable()) { | ||
145 | thread_.join(); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | void TearDown() override { | ||
150 | Close(); | ||
151 | } | ||
152 | }; | ||
153 | |||
154 | } // namespace | ||
155 | |||
156 | TEST_F(FuseAppLoopTest, LookUp) { | ||
157 | request_.Reset(3u, FUSE_LOOKUP, 1); | ||
158 | request_.header.nodeid = FUSE_ROOT_ID; | ||
159 | strcpy(request_.lookup_name, "10"); | ||
160 | |||
161 | ASSERT_TRUE(request_.Write(sockets_[0].get())); | ||
162 | ASSERT_TRUE(response_.Read(sockets_[0].get())); | ||
163 | |||
164 | EXPECT_EQ(kFuseSuccess, response_.header.error); | ||
165 | EXPECT_EQ(sizeof(fuse_out_header) + sizeof(fuse_entry_out), | ||
166 | response_.header.len); | ||
167 | EXPECT_EQ(1u, response_.header.unique); | ||
168 | |||
169 | EXPECT_EQ(10u, response_.entry_out.nodeid); | ||
170 | EXPECT_EQ(0u, response_.entry_out.generation); | ||
171 | EXPECT_EQ(10u, response_.entry_out.entry_valid); | ||
172 | EXPECT_EQ(10u, response_.entry_out.attr_valid); | ||
173 | EXPECT_EQ(0u, response_.entry_out.entry_valid_nsec); | ||
174 | EXPECT_EQ(0u, response_.entry_out.attr_valid_nsec); | ||
175 | |||
176 | EXPECT_EQ(10u, response_.entry_out.attr.ino); | ||
177 | EXPECT_EQ(kTestFileSize, response_.entry_out.attr.size); | ||
178 | EXPECT_EQ(0u, response_.entry_out.attr.blocks); | ||
179 | EXPECT_EQ(0u, response_.entry_out.attr.atime); | ||
180 | EXPECT_EQ(0u, response_.entry_out.attr.mtime); | ||
181 | EXPECT_EQ(0u, response_.entry_out.attr.ctime); | ||
182 | EXPECT_EQ(0u, response_.entry_out.attr.atimensec); | ||
183 | EXPECT_EQ(0u, response_.entry_out.attr.mtimensec); | ||
184 | EXPECT_EQ(0u, response_.entry_out.attr.ctimensec); | ||
185 | EXPECT_EQ(S_IFREG | 0777u, response_.entry_out.attr.mode); | ||
186 | EXPECT_EQ(0u, response_.entry_out.attr.nlink); | ||
187 | EXPECT_EQ(0u, response_.entry_out.attr.uid); | ||
188 | EXPECT_EQ(0u, response_.entry_out.attr.gid); | ||
189 | EXPECT_EQ(0u, response_.entry_out.attr.rdev); | ||
190 | EXPECT_EQ(0u, response_.entry_out.attr.blksize); | ||
191 | EXPECT_EQ(0u, response_.entry_out.attr.padding); | ||
192 | } | ||
193 | |||
194 | TEST_F(FuseAppLoopTest, LookUp_InvalidName) { | ||
195 | request_.Reset(3u, FUSE_LOOKUP, 1); | ||
196 | request_.header.nodeid = FUSE_ROOT_ID; | ||
197 | strcpy(request_.lookup_name, "aa"); | ||
198 | |||
199 | ASSERT_TRUE(request_.Write(sockets_[0].get())); | ||
200 | ASSERT_TRUE(response_.Read(sockets_[0].get())); | ||
201 | |||
202 | EXPECT_EQ(sizeof(fuse_out_header), response_.header.len); | ||
203 | EXPECT_EQ(-ENOENT, response_.header.error); | ||
204 | EXPECT_EQ(1u, response_.header.unique); | ||
205 | } | ||
206 | |||
207 | TEST_F(FuseAppLoopTest, LookUp_TooLargeName) { | ||
208 | request_.Reset(21u, FUSE_LOOKUP, 1); | ||
209 | request_.header.nodeid = FUSE_ROOT_ID; | ||
210 | strcpy(request_.lookup_name, "18446744073709551616"); | ||
211 | |||
212 | ASSERT_TRUE(request_.Write(sockets_[0].get())); | ||
213 | ASSERT_TRUE(response_.Read(sockets_[0].get())); | ||
214 | |||
215 | EXPECT_EQ(sizeof(fuse_out_header), response_.header.len); | ||
216 | EXPECT_EQ(-ENOENT, response_.header.error); | ||
217 | EXPECT_EQ(1u, response_.header.unique); | ||
218 | } | ||
219 | |||
220 | TEST_F(FuseAppLoopTest, GetAttr) { | ||
221 | request_.Reset(sizeof(fuse_getattr_in), FUSE_GETATTR, 1); | ||
222 | request_.header.nodeid = 10; | ||
223 | |||
224 | ASSERT_TRUE(request_.Write(sockets_[0].get())); | ||
225 | ASSERT_TRUE(response_.Read(sockets_[0].get())); | ||
226 | |||
227 | EXPECT_EQ(kFuseSuccess, response_.header.error); | ||
228 | EXPECT_EQ(sizeof(fuse_out_header) + sizeof(fuse_attr_out), | ||
229 | response_.header.len); | ||
230 | EXPECT_EQ(1u, response_.header.unique); | ||
231 | |||
232 | EXPECT_EQ(10u, response_.attr_out.attr_valid); | ||
233 | EXPECT_EQ(0u, response_.attr_out.attr_valid_nsec); | ||
234 | |||
235 | EXPECT_EQ(10u, response_.attr_out.attr.ino); | ||
236 | EXPECT_EQ(kTestFileSize, response_.attr_out.attr.size); | ||
237 | EXPECT_EQ(0u, response_.attr_out.attr.blocks); | ||
238 | EXPECT_EQ(0u, response_.attr_out.attr.atime); | ||
239 | EXPECT_EQ(0u, response_.attr_out.attr.mtime); | ||
240 | EXPECT_EQ(0u, response_.attr_out.attr.ctime); | ||
241 | EXPECT_EQ(0u, response_.attr_out.attr.atimensec); | ||
242 | EXPECT_EQ(0u, response_.attr_out.attr.mtimensec); | ||
243 | EXPECT_EQ(0u, response_.attr_out.attr.ctimensec); | ||
244 | EXPECT_EQ(S_IFREG | 0777u, response_.attr_out.attr.mode); | ||
245 | EXPECT_EQ(0u, response_.attr_out.attr.nlink); | ||
246 | EXPECT_EQ(0u, response_.attr_out.attr.uid); | ||
247 | EXPECT_EQ(0u, response_.attr_out.attr.gid); | ||
248 | EXPECT_EQ(0u, response_.attr_out.attr.rdev); | ||
249 | EXPECT_EQ(0u, response_.attr_out.attr.blksize); | ||
250 | EXPECT_EQ(0u, response_.attr_out.attr.padding); | ||
251 | } | ||
252 | |||
253 | TEST_F(FuseAppLoopTest, GetAttr_Root) { | ||
254 | request_.Reset(sizeof(fuse_getattr_in), FUSE_GETATTR, 1); | ||
255 | request_.header.nodeid = FUSE_ROOT_ID; | ||
256 | |||
257 | ASSERT_TRUE(request_.Write(sockets_[0].get())); | ||
258 | ASSERT_TRUE(response_.Read(sockets_[0].get())); | ||
259 | |||
260 | EXPECT_EQ(kFuseSuccess, response_.header.error); | ||
261 | EXPECT_EQ(sizeof(fuse_out_header) + sizeof(fuse_attr_out), | ||
262 | response_.header.len); | ||
263 | EXPECT_EQ(1u, response_.header.unique); | ||
264 | |||
265 | EXPECT_EQ(10u, response_.attr_out.attr_valid); | ||
266 | EXPECT_EQ(0u, response_.attr_out.attr_valid_nsec); | ||
267 | |||
268 | EXPECT_EQ(static_cast<unsigned>(FUSE_ROOT_ID), response_.attr_out.attr.ino); | ||
269 | EXPECT_EQ(0u, response_.attr_out.attr.size); | ||
270 | EXPECT_EQ(0u, response_.attr_out.attr.blocks); | ||
271 | EXPECT_EQ(0u, response_.attr_out.attr.atime); | ||
272 | EXPECT_EQ(0u, response_.attr_out.attr.mtime); | ||
273 | EXPECT_EQ(0u, response_.attr_out.attr.ctime); | ||
274 | EXPECT_EQ(0u, response_.attr_out.attr.atimensec); | ||
275 | EXPECT_EQ(0u, response_.attr_out.attr.mtimensec); | ||
276 | EXPECT_EQ(0u, response_.attr_out.attr.ctimensec); | ||
277 | EXPECT_EQ(S_IFDIR | 0777u, response_.attr_out.attr.mode); | ||
278 | EXPECT_EQ(0u, response_.attr_out.attr.nlink); | ||
279 | EXPECT_EQ(0u, response_.attr_out.attr.uid); | ||
280 | EXPECT_EQ(0u, response_.attr_out.attr.gid); | ||
281 | EXPECT_EQ(0u, response_.attr_out.attr.rdev); | ||
282 | EXPECT_EQ(0u, response_.attr_out.attr.blksize); | ||
283 | EXPECT_EQ(0u, response_.attr_out.attr.padding); | ||
284 | } | ||
285 | |||
286 | TEST_F(FuseAppLoopTest, Open) { | ||
287 | CheckCallback(sizeof(fuse_open_in), FUSE_OPEN, sizeof(fuse_open_out)); | ||
288 | } | ||
289 | |||
290 | TEST_F(FuseAppLoopTest, Fsync) { | ||
291 | CheckCallback(0u, FUSE_FSYNC, 0u); | ||
292 | } | ||
293 | |||
294 | TEST_F(FuseAppLoopTest, Release) { | ||
295 | CheckCallback(0u, FUSE_RELEASE, 0u); | ||
296 | } | ||
297 | |||
298 | TEST_F(FuseAppLoopTest, Read) { | ||
299 | CheckCallback(sizeof(fuse_read_in), FUSE_READ, 0u); | ||
300 | } | ||
301 | |||
302 | TEST_F(FuseAppLoopTest, Write) { | ||
303 | CheckCallback(sizeof(fuse_write_in), FUSE_WRITE, sizeof(fuse_write_out)); | ||
304 | } | ||
305 | |||
306 | } // namespace fuse | ||
307 | } // namespace android | ||
diff --git a/libappfuse/tests/FuseBridgeLoopTest.cc b/libappfuse/tests/FuseBridgeLoopTest.cc index 31e369041..bd503ebfb 100644 --- a/libappfuse/tests/FuseBridgeLoopTest.cc +++ b/libappfuse/tests/FuseBridgeLoopTest.cc | |||
@@ -21,11 +21,15 @@ | |||
21 | #include <sstream> | 21 | #include <sstream> |
22 | #include <thread> | 22 | #include <thread> |
23 | 23 | ||
24 | #include <android-base/logging.h> | ||
25 | #include <android-base/unique_fd.h> | ||
24 | #include <gtest/gtest.h> | 26 | #include <gtest/gtest.h> |
25 | 27 | ||
26 | namespace android { | 28 | namespace android { |
29 | namespace fuse { | ||
30 | namespace { | ||
27 | 31 | ||
28 | class Callback : public FuseBridgeLoop::Callback { | 32 | class Callback : public FuseBridgeLoopCallback { |
29 | public: | 33 | public: |
30 | bool mounted; | 34 | bool mounted; |
31 | Callback() : mounted(false) {} | 35 | Callback() : mounted(false) {} |
@@ -36,20 +40,28 @@ class Callback : public FuseBridgeLoop::Callback { | |||
36 | 40 | ||
37 | class FuseBridgeLoopTest : public ::testing::Test { | 41 | class FuseBridgeLoopTest : public ::testing::Test { |
38 | protected: | 42 | protected: |
39 | int dev_sockets_[2]; | 43 | base::unique_fd dev_sockets_[2]; |
40 | int proxy_sockets_[2]; | 44 | base::unique_fd proxy_sockets_[2]; |
41 | Callback callback_; | 45 | Callback callback_; |
42 | std::thread thread_; | 46 | std::thread thread_; |
43 | 47 | ||
44 | FuseRequest request_; | 48 | FuseRequest request_; |
45 | FuseResponse response_; | 49 | FuseResponse response_; |
46 | 50 | ||
47 | void SetUp() { | 51 | void SetUp() override { |
48 | ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, dev_sockets_)); | 52 | base::SetMinimumLogSeverity(base::VERBOSE); |
49 | ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, proxy_sockets_)); | 53 | int dev_sockets[2]; |
54 | int proxy_sockets[2]; | ||
55 | ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, dev_sockets)); | ||
56 | ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, proxy_sockets)); | ||
57 | dev_sockets_[0].reset(dev_sockets[0]); | ||
58 | dev_sockets_[1].reset(dev_sockets[1]); | ||
59 | proxy_sockets_[0].reset(proxy_sockets[0]); | ||
60 | proxy_sockets_[1].reset(proxy_sockets[1]); | ||
61 | |||
50 | thread_ = std::thread([this] { | 62 | thread_ = std::thread([this] { |
51 | FuseBridgeLoop loop; | 63 | StartFuseBridgeLoop( |
52 | loop.Start(dev_sockets_[1], proxy_sockets_[0], &callback_); | 64 | dev_sockets_[1].release(), proxy_sockets_[0].release(), &callback_); |
53 | }); | 65 | }); |
54 | } | 66 | } |
55 | 67 | ||
@@ -103,20 +115,22 @@ class FuseBridgeLoopTest : public ::testing::Test { | |||
103 | } | 115 | } |
104 | 116 | ||
105 | void Close() { | 117 | void Close() { |
106 | close(dev_sockets_[0]); | 118 | dev_sockets_[0].reset(); |
107 | close(dev_sockets_[1]); | 119 | dev_sockets_[1].reset(); |
108 | close(proxy_sockets_[0]); | 120 | proxy_sockets_[0].reset(); |
109 | close(proxy_sockets_[1]); | 121 | proxy_sockets_[1].reset(); |
110 | if (thread_.joinable()) { | 122 | if (thread_.joinable()) { |
111 | thread_.join(); | 123 | thread_.join(); |
112 | } | 124 | } |
113 | } | 125 | } |
114 | 126 | ||
115 | void TearDown() { | 127 | void TearDown() override { |
116 | Close(); | 128 | Close(); |
117 | } | 129 | } |
118 | }; | 130 | }; |
119 | 131 | ||
132 | } // namespace | ||
133 | |||
120 | TEST_F(FuseBridgeLoopTest, FuseInit) { | 134 | TEST_F(FuseBridgeLoopTest, FuseInit) { |
121 | SendInitRequest(1u); | 135 | SendInitRequest(1u); |
122 | 136 | ||
@@ -156,11 +170,11 @@ TEST_F(FuseBridgeLoopTest, FuseNotImpl) { | |||
156 | CheckNotImpl(FUSE_RENAME); | 170 | CheckNotImpl(FUSE_RENAME); |
157 | CheckNotImpl(FUSE_LINK); | 171 | CheckNotImpl(FUSE_LINK); |
158 | CheckNotImpl(FUSE_STATFS); | 172 | CheckNotImpl(FUSE_STATFS); |
159 | CheckNotImpl(FUSE_FSYNC); | ||
160 | CheckNotImpl(FUSE_SETXATTR); | 173 | CheckNotImpl(FUSE_SETXATTR); |
161 | CheckNotImpl(FUSE_GETXATTR); | 174 | CheckNotImpl(FUSE_GETXATTR); |
162 | CheckNotImpl(FUSE_LISTXATTR); | 175 | CheckNotImpl(FUSE_LISTXATTR); |
163 | CheckNotImpl(FUSE_REMOVEXATTR); | 176 | CheckNotImpl(FUSE_REMOVEXATTR); |
177 | CheckNotImpl(FUSE_FLUSH); | ||
164 | CheckNotImpl(FUSE_OPENDIR); | 178 | CheckNotImpl(FUSE_OPENDIR); |
165 | CheckNotImpl(FUSE_READDIR); | 179 | CheckNotImpl(FUSE_READDIR); |
166 | CheckNotImpl(FUSE_RELEASEDIR); | 180 | CheckNotImpl(FUSE_RELEASEDIR); |
@@ -190,7 +204,8 @@ TEST_F(FuseBridgeLoopTest, Proxy) { | |||
190 | CheckProxy(FUSE_READ); | 204 | CheckProxy(FUSE_READ); |
191 | CheckProxy(FUSE_WRITE); | 205 | CheckProxy(FUSE_WRITE); |
192 | CheckProxy(FUSE_RELEASE); | 206 | CheckProxy(FUSE_RELEASE); |
193 | CheckProxy(FUSE_FLUSH); | 207 | CheckProxy(FUSE_FSYNC); |
194 | } | 208 | } |
195 | 209 | ||
196 | } // android | 210 | } // namespace fuse |
211 | } // namespace android | ||
diff --git a/libappfuse/tests/FuseBufferTest.cc b/libappfuse/tests/FuseBufferTest.cc index 1aacfe303..17f1306fe 100644 --- a/libappfuse/tests/FuseBufferTest.cc +++ b/libappfuse/tests/FuseBufferTest.cc | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <gtest/gtest.h> | 24 | #include <gtest/gtest.h> |
25 | 25 | ||
26 | namespace android { | 26 | namespace android { |
27 | namespace fuse { | ||
27 | 28 | ||
28 | constexpr char kTempFile[] = "/data/local/tmp/appfuse_test_dump"; | 29 | constexpr char kTempFile[] = "/data/local/tmp/appfuse_test_dump"; |
29 | 30 | ||
@@ -183,5 +184,6 @@ TEST(FuseBufferTest, HandleNotImpl) { | |||
183 | ASSERT_EQ(sizeof(fuse_out_header), buffer.response.header.len); | 184 | ASSERT_EQ(sizeof(fuse_out_header), buffer.response.header.len); |
184 | EXPECT_EQ(-ENOSYS, buffer.response.header.error); | 185 | EXPECT_EQ(-ENOSYS, buffer.response.header.error); |
185 | } | 186 | } |
186 | } | 187 | |
187 | // namespace android | 188 | } // namespace fuse |
189 | } // namespace android | ||