From f36e7c5806dbe8d96e20a4632b805d814ac14b01 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sun, 7 Jul 2013 03:52:37 -0700 Subject: Support for building on Android --- android/statvfs.c | 48 +++++++++++++++++++++++++++++++++++++++ android/sys/statvfs.h | 39 ++++++++++++++++++++++++++++++++ include/fuse.h | 3 +++ include/fuse_common.h | 8 +++++++ include/fuse_compat.h | 2 ++ include/fuse_lowlevel_compat.h | 2 ++ include/ulockmgr.h | 2 ++ lib/Android.mk | 51 ++++++++++++++++++++++++++++++++++++++++++ lib/buffer.c | 2 +- lib/fuse.c | 33 ++++++++++++++++++++++----- lib/fuse_loop_mt.c | 31 +++++++++++++++++++++++++ lib/fuse_mt.c | 2 +- lib/fuse_session.c | 9 +++++--- lib/fuse_versionscript | 3 +++ lib/helper.c | 6 ++--- lib/mount.c | 4 ++++ lib/mount_util.c | 5 +++++ 17 files changed, 237 insertions(+), 13 deletions(-) create mode 100644 android/statvfs.c create mode 100644 android/sys/statvfs.h create mode 100644 lib/Android.mk diff --git a/android/statvfs.c b/android/statvfs.c new file mode 100644 index 0000000..7cec574 --- /dev/null +++ b/android/statvfs.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "sys/statvfs.h" +#include + +#define MAP(to,from) vfs->to = sfs.from + +int statvfs(const char *path, struct statvfs *vfs) { + struct statfs sfs; + int ret; + int *fsid; + if ((ret = statfs(path, &sfs)) != 0) + return ret; + + MAP(f_bsize, f_bsize); + MAP(f_frsize, f_frsize); + MAP(f_blocks, f_blocks); + MAP(f_bfree, f_bfree); + MAP(f_bavail, f_bavail); + MAP(f_files, f_files); + MAP(f_ffree, f_ffree); + MAP(f_namemax, f_namelen); + + vfs->f_favail = 0; + vfs->f_flag = 0; + + fsid = (int *)&sfs.f_fsid; + vfs->f_fsid = (fsid[0] << sizeof(fsid[0])) | fsid[1]; + + return ret; +} diff --git a/android/sys/statvfs.h b/android/sys/statvfs.h new file mode 100644 index 0000000..0d770dd --- /dev/null +++ b/android/sys/statvfs.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _SYS_STATVFS_H_ +#define _SYS_STATVFS_H_ +#include + +struct statvfs { + unsigned long f_bsize; /* file system block size */ + unsigned long f_frsize; /* fragment size */ + fsblkcnt_t f_blocks; /* size of fs in f_frsize units */ + fsblkcnt_t f_bfree; /* # free blocks */ + fsblkcnt_t f_bavail; /* # free blocks for non-root */ + fsfilcnt_t f_files; /* # inodes */ + fsfilcnt_t f_ffree; /* # free inodes */ + fsfilcnt_t f_favail; /* # free inodes for non-root */ + unsigned long f_fsid; /* file system ID */ + unsigned long f_flag; /* mount flags */ + unsigned long f_namemax; /* maximum filename length */ +}; + +int statvfs(const char *, struct statvfs *); +#endif diff --git a/include/fuse.h b/include/fuse.h index c657e67..6ad8ee7 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -30,6 +30,9 @@ #include #include #include +#if defined(__ANDROID__) +#include +#endif #include #include diff --git a/include/fuse_common.h b/include/fuse_common.h index a4d980d..882caf0 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -15,6 +15,10 @@ #ifndef _FUSE_COMMON_H_ #define _FUSE_COMMON_H_ +#if defined(__ANDROID__) +#define _OFF_T_DEFINED_ +#endif + #include "fuse_opt.h" #include #include @@ -33,6 +37,10 @@ #error Please add -D_FILE_OFFSET_BITS=64 to your compile flags! #endif +#if defined(__ANDROID__) +typedef loff_t off_t; +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/include/fuse_compat.h b/include/fuse_compat.h index e7497a9..3bfaa25 100644 --- a/include/fuse_compat.h +++ b/include/fuse_compat.h @@ -9,6 +9,8 @@ /* these definitions provide source compatibility to prior versions. Do not include this file directly! */ +#include "fuse_lowlevel.h" + struct fuse_operations_compat25 { int (*getattr) (const char *, struct stat *); int (*readlink) (const char *, char *, size_t); diff --git a/include/fuse_lowlevel_compat.h b/include/fuse_lowlevel_compat.h index 8de220b..4fff57a 100644 --- a/include/fuse_lowlevel_compat.h +++ b/include/fuse_lowlevel_compat.h @@ -9,6 +9,8 @@ /* these definitions provide source compatibility to prior versions. Do not include this file directly! */ +#include "fuse_common.h" + struct fuse_lowlevel_ops_compat25 { void (*init) (void *userdata); void (*destroy) (void *userdata); diff --git a/include/ulockmgr.h b/include/ulockmgr.h index ad55579..c3ceef5 100644 --- a/include/ulockmgr.h +++ b/include/ulockmgr.h @@ -6,6 +6,8 @@ See the file COPYING.LIB. */ +#include "fuse_lowlevel.h" + #include #include #include diff --git a/lib/Android.mk b/lib/Android.mk new file mode 100644 index 0000000..a2b1231 --- /dev/null +++ b/lib/Android.mk @@ -0,0 +1,51 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + ../android/statvfs.c \ + buffer.c \ + cuse_lowlevel.c \ + fuse.c \ + fuse_kern_chan.c \ + fuse_loop.c \ + fuse_loop_mt.c \ + fuse_lowlevel.c \ + fuse_mt.c fuse_opt.c \ + fuse_session.c \ + fuse_signals.c \ + helper.c \ + mount.c \ + mount_util.c \ + ulockmgr.c + +LOCAL_C_INCLUDES := \ + external/fuse/android \ + external/fuse/include + +LOCAL_SHARED_LIBRARIES := \ + libutils libdl + +LOCAL_CFLAGS := \ + -D_FILE_OFFSET_BITS=64 \ + -DFUSE_USE_VERSION=26 + +LOCAL_MODULE := libfuse +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) + diff --git a/lib/buffer.c b/lib/buffer.c index 17a595c..0078e11 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -45,7 +45,7 @@ static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off, while (len) { if (dst->flags & FUSE_BUF_FD_SEEK) { - res = pwrite(dst->fd, src->mem + src_off, len, + res = pwrite64(dst->fd, src->mem + src_off, len, dst->pos + dst_off); } else { res = write(dst->fd, src->mem + src_off, len); diff --git a/lib/fuse.c b/lib/fuse.c index 067d0dc..e456515 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -4558,11 +4558,30 @@ static int node_table_init(struct node_table *t) return 0; } +static void thread_exit_handler(int sig) +{ + pthread_exit(0); +} + static void *fuse_prune_nodes(void *fuse) { struct fuse *f = fuse; int sleep_time; +#if defined(__ANDROID__) + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_exit_handler; + sigaction(SIGUSR1, &actions, NULL); + + sigset_t setusr1; + sigemptyset(&setusr1); + sigaddset(&setusr1, SIGUSR1); + pthread_sigmask(SIG_BLOCK, &setusr1, NULL); +#endif + while(1) { sleep_time = fuse_clean_cache(f); sleep(sleep_time); @@ -4582,7 +4601,11 @@ void fuse_stop_cleanup_thread(struct fuse *f) { if (lru_enabled(f)) { pthread_mutex_lock(&f->lock); +#if defined(__ANDROID__) + pthread_kill(f->prune_thread, SIGUSR1); +#else pthread_cancel(f->prune_thread); +#endif pthread_mutex_unlock(&f->lock); pthread_join(f->prune_thread, NULL); } @@ -4873,11 +4896,11 @@ struct fuse *fuse_new_compat1(int fd, int flags, 11); } -FUSE_SYMVER(".symver fuse_exited,__fuse_exited@"); -FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@"); -FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@"); -FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@"); -FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@"); +FUSE_SYMVER(".symver fuse_exited,__fuse_exited@FUSE_UNVERSIONED"); +FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@FUSE_UNVERSIONED"); +FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@FUSE_UNVERSIONED"); +FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@FUSE_UNVERSIONED"); +FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@FUSE_UNVERSIONED"); FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2"); #endif /* __FreeBSD__ || __NetBSD__ */ diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 82e3001..90fc1e6 100644 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -63,11 +63,30 @@ static void list_del_worker(struct fuse_worker *w) static int fuse_loop_start_thread(struct fuse_mt *mt); +static void thread_exit_handler(int sig) +{ + pthread_exit(0); +} + static void *fuse_do_work(void *data) { struct fuse_worker *w = (struct fuse_worker *) data; struct fuse_mt *mt = w->mt; +#if defined(__ANDROID__) + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_exit_handler; + sigaction(SIGUSR1, &actions, NULL); + + sigset_t setusr1; + sigemptyset(&setusr1); + sigaddset(&setusr1, SIGUSR1); + pthread_sigmask(SIG_BLOCK, &setusr1, NULL); +#endif + while (!fuse_session_exited(mt->se)) { int isforget = 0; struct fuse_chan *ch = mt->prevch; @@ -77,9 +96,17 @@ static void *fuse_do_work(void *data) }; int res; +#if defined(__ANDROID__) + pthread_sigmask(SIG_UNBLOCK, &setusr1, NULL); +#else pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); +#endif res = fuse_session_receive_buf(mt->se, &fbuf, &ch); +#if defined(__ANDROID__) + pthread_sigmask(SIG_BLOCK, &setusr1, NULL); +#else pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); +#endif if (res == -EINTR) continue; if (res <= 0) { @@ -243,7 +270,11 @@ int fuse_session_loop_mt(struct fuse_session *se) pthread_mutex_lock(&mt.lock); for (w = mt.main.next; w != &mt.main; w = w->next) +#if defined(__ANDROID__) + pthread_kill(w->thread_id, SIGUSR1); +#else pthread_cancel(w->thread_id); +#endif mt.exit = 1; pthread_mutex_unlock(&mt.lock); diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c index f6dbe71..fd5ac23 100644 --- a/lib/fuse_mt.c +++ b/lib/fuse_mt.c @@ -119,4 +119,4 @@ int fuse_loop_mt(struct fuse *f) return res; } -FUSE_SYMVER(".symver fuse_loop_mt_proc,__fuse_loop_mt@"); +FUSE_SYMVER(".symver fuse_loop_mt_proc,__fuse_loop_mt@FUSE_UNVERSIONED"); diff --git a/lib/fuse_session.c b/lib/fuse_session.c index 6e11068..18c8c42 100644 --- a/lib/fuse_session.c +++ b/lib/fuse_session.c @@ -184,9 +184,12 @@ int fuse_chan_fd(struct fuse_chan *ch) int fuse_chan_clearfd(struct fuse_chan *ch) { - int fd = ch->fd; - ch->fd = -1; - return fd; + if (ch == NULL) + return -1; + + int fd = ch->fd; + ch->fd = -1; + return fd; } size_t fuse_chan_bufsize(struct fuse_chan *ch) diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 8d91887..de16ab2 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -1,3 +1,6 @@ +FUSE_UNVERSIONED { +}; + FUSE_2.2 { global: fuse_destroy; diff --git a/lib/helper.c b/lib/helper.c index b644012..c5349bf 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -436,10 +436,10 @@ int fuse_mount_compat1(const char *mountpoint, const char *args[]) return fuse_mount_compat22(mountpoint, NULL); } -FUSE_SYMVER(".symver fuse_setup_compat2,__fuse_setup@"); +FUSE_SYMVER(".symver fuse_setup_compat2,__fuse_setup@FUSE_UNVERSIONED"); FUSE_SYMVER(".symver fuse_setup_compat22,fuse_setup@FUSE_2.2"); -FUSE_SYMVER(".symver fuse_teardown,__fuse_teardown@"); -FUSE_SYMVER(".symver fuse_main_compat2,fuse_main@"); +FUSE_SYMVER(".symver fuse_teardown,__fuse_teardown@FUSE_UNVERSIONED"); +FUSE_SYMVER(".symver fuse_main_compat2,fuse_main@FUSE_UNVERSIONED"); FUSE_SYMVER(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2"); #endif /* __FreeBSD__ || __NetBSD__ */ diff --git a/lib/mount.c b/lib/mount.c index 0f767c8..2a557c6 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -42,6 +42,10 @@ #define FUSERMOUNT_PROG "fusermount" #define FUSE_COMMFD_ENV "_FUSE_COMMFD" +#if defined(__ANDROID__) && !defined(FUSERMOUNT_DIR) +# define FUSERMOUNT_DIR "/system/xbin" +#endif + #ifndef HAVE_FORK #define fork() vfork() #endif diff --git a/lib/mount_util.c b/lib/mount_util.c index 3d2f4cd..e8bd538 100644 --- a/lib/mount_util.c +++ b/lib/mount_util.c @@ -23,10 +23,15 @@ #include #include #include +#if defined(__ANDROID__) +#include +#endif #ifdef __NetBSD__ #define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0) #define mtab_needs_update(mnt) 0 +#elif defined(__ANDROID__) +#define mtab_needs_update(mnt) 0 #else static int mtab_needs_update(const char *mnt) { -- cgit v1.2.3