blob: cde28fce1cc5e078c6113c3d9d95c75bb5f23afc [file] [log] [blame]
Daichi Hironobee50c02015-12-14 11:00:54 +09001/*
2 * Copyright (C) 2015 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#define LOG_NDEBUG 0
18#define LOG_TAG "AppFuseJNI"
19#include "utils/Log.h"
20
21#include <assert.h>
22#include <dirent.h>
23#include <inttypes.h>
24
25#include <linux/fuse.h>
26#include <sys/stat.h>
27
28#include <map>
29
30#include "jni.h"
31#include "JNIHelp.h"
32#include "android_runtime/AndroidRuntime.h"
Daichi Hironocc9a7d72015-10-28 09:43:48 +090033#include "nativehelper/ScopedPrimitiveArray.h"
Daichi Hironobee50c02015-12-14 11:00:54 +090034
35namespace {
36
Daichi Hirono2153e8222016-01-11 17:43:55 +090037// The numbers came from sdcard.c.
38// Maximum number of bytes to write/read in one request/one reply.
Daichi Hironobee50c02015-12-14 11:00:54 +090039constexpr size_t MAX_WRITE = 256 * 1024;
Daichi Hirono2153e8222016-01-11 17:43:55 +090040constexpr size_t MAX_READ = 128 * 1024;
41
Daichi Hironocc9a7d72015-10-28 09:43:48 +090042constexpr size_t NUM_MAX_HANDLES = 1024;
Daichi Hironobee50c02015-12-14 11:00:54 +090043
44// Largest possible request.
45// The request size is bounded by the maximum size of a FUSE_WRITE request
46// because it has the largest possible data payload.
47constexpr size_t MAX_REQUEST_SIZE = sizeof(struct fuse_in_header) +
Daichi Hironofab4a972016-01-15 16:54:24 +090048 sizeof(struct fuse_write_in) + (MAX_WRITE > MAX_READ ? MAX_WRITE : MAX_READ);
Daichi Hironobee50c02015-12-14 11:00:54 +090049
50static jclass app_fuse_class;
Daichi Hironocc9a7d72015-10-28 09:43:48 +090051static jmethodID app_fuse_get_file_size;
52static jmethodID app_fuse_get_object_bytes;
Daichi Hironobee50c02015-12-14 11:00:54 +090053
Daichi Hirono2153e8222016-01-11 17:43:55 +090054// NOTE:
55// FuseRequest and FuseResponse shares the same buffer to save memory usage, so the handlers must
56// not access input buffer after writing data to output buffer.
Daichi Hironobee50c02015-12-14 11:00:54 +090057struct FuseRequest {
58 char buffer[MAX_REQUEST_SIZE];
59 FuseRequest() {}
60 const struct fuse_in_header& header() const {
61 return *(const struct fuse_in_header*) buffer;
62 }
Daichi Hirono2153e8222016-01-11 17:43:55 +090063 void* data() {
Daichi Hironobee50c02015-12-14 11:00:54 +090064 return (buffer + sizeof(struct fuse_in_header));
65 }
66 size_t data_length() const {
67 return header().len - sizeof(struct fuse_in_header);
68 }
69};
70
Daichi Hirono2153e8222016-01-11 17:43:55 +090071template<typename T>
72class FuseResponse {
73 size_t size_;
74 T* const buffer_;
75public:
76 FuseResponse(void* buffer) : size_(0), buffer_(static_cast<T*>(buffer)) {}
77
78 void prepare_buffer(size_t size = sizeof(T)) {
79 memset(buffer_, 0, size);
80 size_ = size;
81 }
82
83 void set_size(size_t size) {
84 size_ = size;
85 }
86
87 size_t size() const { return size_; }
88 T* data() const { return buffer_; }
89};
90
Daichi Hirono91e3b502015-12-16 09:24:16 +090091class ScopedFd {
92 int mFd;
93
94public:
95 explicit ScopedFd(int fd) : mFd(fd) {}
96 ~ScopedFd() {
97 close(mFd);
98 }
99 operator int() {
100 return mFd;
101 }
102};
103
Daichi Hironobee50c02015-12-14 11:00:54 +0900104/**
Daichi Hirono2153e8222016-01-11 17:43:55 +0900105 * Fuse implementation consists of handlers parsing FUSE commands.
Daichi Hironobee50c02015-12-14 11:00:54 +0900106 */
107class AppFuse {
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900108 JNIEnv* env_;
109 jobject self_;
110
111 // Map between file handle and inode.
112 std::map<uint32_t, uint64_t> handles_;
113 uint32_t handle_counter_;
114
Daichi Hironobee50c02015-12-14 11:00:54 +0900115public:
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900116 AppFuse(JNIEnv* env, jobject self) :
117 env_(env), self_(self), handle_counter_(0) {}
Daichi Hironobee50c02015-12-14 11:00:54 +0900118
Daichi Hirono2153e8222016-01-11 17:43:55 +0900119 bool handle_fuse_request(int fd, FuseRequest* req) {
120 ALOGV("Request op=%d", req->header().opcode);
121 switch (req->header().opcode) {
Daichi Hironobee50c02015-12-14 11:00:54 +0900122 // TODO: Handle more operations that are enough to provide seekable
123 // FD.
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900124 case FUSE_LOOKUP:
125 invoke_handler(fd, req, &AppFuse::handle_fuse_lookup);
126 return true;
Daichi Hironobee50c02015-12-14 11:00:54 +0900127 case FUSE_INIT:
128 invoke_handler(fd, req, &AppFuse::handle_fuse_init);
Daichi Hirono91e3b502015-12-16 09:24:16 +0900129 return true;
Daichi Hironobee50c02015-12-14 11:00:54 +0900130 case FUSE_GETATTR:
131 invoke_handler(fd, req, &AppFuse::handle_fuse_getattr);
Daichi Hirono91e3b502015-12-16 09:24:16 +0900132 return true;
133 case FUSE_FORGET:
134 return false;
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900135 case FUSE_OPEN:
136 invoke_handler(fd, req, &AppFuse::handle_fuse_open);
137 return true;
138 case FUSE_READ:
Daichi Hirono2153e8222016-01-11 17:43:55 +0900139 invoke_handler(fd, req, &AppFuse::handle_fuse_read);
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900140 return true;
141 case FUSE_RELEASE:
Daichi Hirono2153e8222016-01-11 17:43:55 +0900142 invoke_handler(fd, req, &AppFuse::handle_fuse_release);
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900143 return true;
144 case FUSE_FLUSH:
Daichi Hirono2153e8222016-01-11 17:43:55 +0900145 invoke_handler(fd, req, &AppFuse::handle_fuse_flush);
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900146 return true;
Daichi Hironobee50c02015-12-14 11:00:54 +0900147 default: {
148 ALOGV("NOTIMPL op=%d uniq=%" PRIx64 " nid=%" PRIx64 "\n",
Daichi Hirono2153e8222016-01-11 17:43:55 +0900149 req->header().opcode,
150 req->header().unique,
151 req->header().nodeid);
152 fuse_reply(fd, req->header().unique, -ENOSYS, NULL, 0);
Daichi Hirono91e3b502015-12-16 09:24:16 +0900153 return true;
Daichi Hironobee50c02015-12-14 11:00:54 +0900154 }
155 }
156 }
157
158private:
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900159 int handle_fuse_lookup(const fuse_in_header& header,
160 const char* name,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900161 FuseResponse<fuse_entry_out>* out) {
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900162 if (header.nodeid != 1) {
163 return -ENOENT;
164 }
165
166 const int n = atoi(name);
167 if (n == 0) {
168 return -ENOENT;
169 }
170
171 int64_t size = get_file_size(n);
172 if (size < 0) {
173 return -ENOENT;
174 }
175
Daichi Hirono2153e8222016-01-11 17:43:55 +0900176 out->prepare_buffer();
177 out->data()->nodeid = n;
178 out->data()->attr_valid = 10;
179 out->data()->entry_valid = 10;
180 out->data()->attr.ino = n;
181 out->data()->attr.mode = S_IFREG | 0777;
182 out->data()->attr.size = size;
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900183 return 0;
184 }
185
Daichi Hironobee50c02015-12-14 11:00:54 +0900186 int handle_fuse_init(const fuse_in_header&,
187 const fuse_init_in* in,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900188 FuseResponse<fuse_init_out>* out) {
Daichi Hironobee50c02015-12-14 11:00:54 +0900189 // Kernel 2.6.16 is the first stable kernel with struct fuse_init_out
190 // defined (fuse version 7.6). The structure is the same from 7.6 through
191 // 7.22. Beginning with 7.23, the structure increased in size and added
192 // new parameters.
193 if (in->major != FUSE_KERNEL_VERSION || in->minor < 6) {
194 ALOGE("Fuse kernel version mismatch: Kernel version %d.%d, "
195 "Expected at least %d.6",
196 in->major, in->minor, FUSE_KERNEL_VERSION);
197 return -1;
198 }
199
Daichi Hirono2153e8222016-01-11 17:43:55 +0900200 // Before writing |out|, we need to copy data from |in|.
201 const uint32_t minor = in->minor;
202 const uint32_t max_readahead = in->max_readahead;
203
Daichi Hironobee50c02015-12-14 11:00:54 +0900204 // We limit ourselves to 15 because we don't handle BATCH_FORGET yet
Daichi Hirono2153e8222016-01-11 17:43:55 +0900205 size_t response_size = sizeof(fuse_init_out);
Daichi Hironobee50c02015-12-14 11:00:54 +0900206#if defined(FUSE_COMPAT_22_INIT_OUT_SIZE)
207 // FUSE_KERNEL_VERSION >= 23.
208
209 // If the kernel only works on minor revs older than or equal to 22,
210 // then use the older structure size since this code only uses the 7.22
211 // version of the structure.
Daichi Hirono2153e8222016-01-11 17:43:55 +0900212 if (minor <= 22) {
213 response_size = FUSE_COMPAT_22_INIT_OUT_SIZE;
Daichi Hironobee50c02015-12-14 11:00:54 +0900214 }
Daichi Hironobee50c02015-12-14 11:00:54 +0900215#endif
Daichi Hirono2153e8222016-01-11 17:43:55 +0900216 out->prepare_buffer(response_size);
217 out->data()->major = FUSE_KERNEL_VERSION;
218 out->data()->minor = std::min(minor, 15u);
219 out->data()->max_readahead = max_readahead;
220 out->data()->flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES;
221 out->data()->max_background = 32;
222 out->data()->congestion_threshold = 32;
223 out->data()->max_write = MAX_WRITE;
Daichi Hironobee50c02015-12-14 11:00:54 +0900224
225 return 0;
226 }
227
228 int handle_fuse_getattr(const fuse_in_header& header,
229 const fuse_getattr_in* /* in */,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900230 FuseResponse<fuse_attr_out>* out) {
231 out->prepare_buffer();
232 out->data()->attr_valid = 10;
233 out->data()->attr.ino = header.nodeid;
234 if (header.nodeid == 1) {
235 out->data()->attr.mode = S_IFDIR | 0777;
236 out->data()->attr.size = 0;
237 } else {
238 int64_t size = get_file_size(header.nodeid);
239 if (size < 0) {
240 return -ENOENT;
241 }
242 out->data()->attr.mode = S_IFREG | 0777;
243 out->data()->attr.size = size;
Daichi Hironobee50c02015-12-14 11:00:54 +0900244 }
Daichi Hirono2153e8222016-01-11 17:43:55 +0900245
Daichi Hironobee50c02015-12-14 11:00:54 +0900246 return 0;
247 }
248
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900249 int handle_fuse_open(const fuse_in_header& header,
250 const fuse_open_in* /* in */,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900251 FuseResponse<fuse_open_out>* out) {
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900252 if (handles_.size() >= NUM_MAX_HANDLES) {
253 // Too many open files.
254 return -EMFILE;
255 }
256 uint32_t handle;
257 do {
258 handle = handle_counter_++;
259 } while (handles_.count(handle) != 0);
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900260 handles_.insert(std::make_pair(handle, header.nodeid));
Daichi Hirono2153e8222016-01-11 17:43:55 +0900261
262 out->prepare_buffer();
263 out->data()->fh = handle;
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900264 return 0;
265 }
266
267 int handle_fuse_read(const fuse_in_header& /* header */,
268 const fuse_read_in* in,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900269 FuseResponse<void>* out) {
270 if (in->size > MAX_READ) {
271 return -EINVAL;
272 }
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900273 const std::map<uint32_t, uint64_t>::iterator it = handles_.find(in->fh);
274 if (it == handles_.end()) {
275 return -EBADF;
276 }
Daichi Hirono2153e8222016-01-11 17:43:55 +0900277 uint64_t offset = in->offset;
278 uint32_t size = in->size;
279
280 // Overwrite the size after writing data.
281 out->prepare_buffer(0);
282 const int64_t result = get_object_bytes(it->second, offset, size, out->data());
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900283 if (result < 0) {
284 return -EIO;
285 }
Daichi Hirono2153e8222016-01-11 17:43:55 +0900286 out->set_size(result);
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900287 return 0;
288 }
289
290 int handle_fuse_release(const fuse_in_header& /* header */,
291 const fuse_release_in* in,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900292 FuseResponse<void>* /* out */) {
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900293 handles_.erase(in->fh);
294 return 0;
295 }
296
297 int handle_fuse_flush(const fuse_in_header& /* header */,
298 const void* /* in */,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900299 FuseResponse<void>* /* out */) {
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900300 return 0;
301 }
302
Daichi Hironobee50c02015-12-14 11:00:54 +0900303 template <typename T, typename S>
304 void invoke_handler(int fd,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900305 FuseRequest* request,
Daichi Hironobee50c02015-12-14 11:00:54 +0900306 int (AppFuse::*handler)(const fuse_in_header&,
307 const T*,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900308 FuseResponse<S>*)) {
309 FuseResponse<S> response(request->data());
Daichi Hironobee50c02015-12-14 11:00:54 +0900310 const int reply_code = (this->*handler)(
Daichi Hirono2153e8222016-01-11 17:43:55 +0900311 request->header(),
312 static_cast<const T*>(request->data()),
313 &response);
Daichi Hironobee50c02015-12-14 11:00:54 +0900314 fuse_reply(
315 fd,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900316 request->header().unique,
Daichi Hironobee50c02015-12-14 11:00:54 +0900317 reply_code,
Daichi Hirono2153e8222016-01-11 17:43:55 +0900318 request->data(),
319 response.size());
Daichi Hironobee50c02015-12-14 11:00:54 +0900320 }
321
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900322 int64_t get_file_size(int inode) {
323 return static_cast<int64_t>(env_->CallLongMethod(
324 self_,
325 app_fuse_get_file_size,
326 static_cast<int>(inode)));
327 }
328
329 int64_t get_object_bytes(
330 int inode,
331 uint64_t offset,
332 uint32_t size,
333 void* buf) {
334 const uint32_t read_size = static_cast<uint32_t>(std::min(
335 static_cast<uint64_t>(size),
336 get_file_size(inode) - offset));
337 const jbyteArray array = (jbyteArray) env_->CallObjectMethod(
338 self_,
339 app_fuse_get_object_bytes,
340 inode,
341 offset,
342 read_size);
343 if (array == nullptr) {
344 return -1;
345 }
346 ScopedByteArrayRO bytes(env_, array);
347 if (bytes.size() != read_size || bytes.get() == nullptr) {
348 return -1;
349 }
350
351 memcpy(buf, bytes.get(), read_size);
352 return read_size;
353 }
354
Daichi Hironobee50c02015-12-14 11:00:54 +0900355 static void fuse_reply(int fd, int unique, int reply_code, void* reply_data,
356 size_t reply_size) {
357 // Don't send any data for error case.
358 if (reply_code != 0) {
359 reply_size = 0;
360 }
361
362 struct fuse_out_header hdr;
363 hdr.len = reply_size + sizeof(hdr);
364 hdr.error = reply_code;
365 hdr.unique = unique;
366
367 struct iovec vec[2];
368 vec[0].iov_base = &hdr;
369 vec[0].iov_len = sizeof(hdr);
370 vec[1].iov_base = reply_data;
371 vec[1].iov_len = reply_size;
372
373 const int res = writev(fd, vec, reply_size != 0 ? 2 : 1);
374 if (res < 0) {
375 ALOGE("*** REPLY FAILED *** %d\n", errno);
376 }
377 }
378};
379
380jboolean com_android_mtp_AppFuse_start_app_fuse_loop(
381 JNIEnv* env, jobject self, jint jfd) {
Daichi Hirono91e3b502015-12-16 09:24:16 +0900382 ScopedFd fd(dup(static_cast<int>(jfd)));
Daichi Hironobee50c02015-12-14 11:00:54 +0900383 AppFuse appfuse(env, self);
384
385 ALOGD("Start fuse loop.");
386 while (true) {
387 FuseRequest request;
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900388
Daichi Hironobee50c02015-12-14 11:00:54 +0900389 const ssize_t result = TEMP_FAILURE_RETRY(
390 read(fd, request.buffer, sizeof(request.buffer)));
391 if (result < 0) {
392 if (errno == ENODEV) {
393 ALOGE("Someone stole our marbles!\n");
Daichi Hirono91e3b502015-12-16 09:24:16 +0900394 return JNI_FALSE;
Daichi Hironobee50c02015-12-14 11:00:54 +0900395 }
396 ALOGE("Failed to read bytes from FD: errno=%d\n", errno);
397 continue;
398 }
399
400 const size_t length = static_cast<size_t>(result);
401 if (length < sizeof(struct fuse_in_header)) {
402 ALOGE("request too short: len=%zu\n", length);
403 continue;
404 }
405
406 if (request.header().len != length) {
407 ALOGE("malformed header: len=%zu, hdr->len=%u\n",
408 length, request.header().len);
409 continue;
410 }
411
Daichi Hirono2153e8222016-01-11 17:43:55 +0900412 if (!appfuse.handle_fuse_request(fd, &request)) {
Daichi Hirono91e3b502015-12-16 09:24:16 +0900413 return JNI_TRUE;
414 }
Daichi Hironobee50c02015-12-14 11:00:54 +0900415 }
416}
417
418static const JNINativeMethod gMethods[] = {
419 {
420 "native_start_app_fuse_loop",
421 "(I)Z",
422 (void *) com_android_mtp_AppFuse_start_app_fuse_loop
423 }
424};
425
426}
427
428jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
429 JNIEnv* env = nullptr;
430 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
431 ALOGE("ERROR: GetEnv failed\n");
432 return -1;
433
434 }
435 assert(env != nullptr);
436
437 jclass clazz = env->FindClass("com/android/mtp/AppFuse");
438 if (clazz == nullptr) {
439 ALOGE("Can't find com/android/mtp/AppFuse");
440 return -1;
441 }
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900442
Daichi Hironobee50c02015-12-14 11:00:54 +0900443 app_fuse_class = static_cast<jclass>(env->NewGlobalRef(clazz));
444 if (app_fuse_class == nullptr) {
445 ALOGE("Can't obtain global reference for com/android/mtp/AppFuse");
446 return -1;
447 }
448
Daichi Hironocc9a7d72015-10-28 09:43:48 +0900449 app_fuse_get_file_size = env->GetMethodID(
450 app_fuse_class, "getFileSize", "(I)J");
451 if (app_fuse_get_file_size == nullptr) {
452 ALOGE("Can't find getFileSize");
453 return -1;
454 }
455
456 app_fuse_get_object_bytes = env->GetMethodID(
457 app_fuse_class, "getObjectBytes", "(IJI)[B");
458 if (app_fuse_get_object_bytes == nullptr) {
459 ALOGE("Can't find getObjectBytes");
460 return -1;
461 }
462
Daichi Hironobee50c02015-12-14 11:00:54 +0900463 const int result = android::AndroidRuntime::registerNativeMethods(
464 env, "com/android/mtp/AppFuse", gMethods, NELEM(gMethods));
465 if (result < 0) {
466 return -1;
467 }
468
469 return JNI_VERSION_1_4;
470}