├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── fuse-ext2.1 ├── fuse-ext2.pc.in ├── fuse-ext2 ├── Makefile.am ├── do_check.c ├── do_fillstatbuf.c ├── do_killfilebyinode.c ├── do_probe.c ├── do_readinode.c ├── do_writeinode.c ├── fuse-ext2.c ├── fuse-ext2.h ├── fuse-ext2.install.m ├── fuse-ext2.probe.c ├── fuse-ext2.uninstall.m ├── fuse-ext2.wait.m ├── op_access.c ├── op_chmod.c ├── op_chown.c ├── op_create.c ├── op_destroy.c ├── op_fgetattr.c ├── op_flush.c ├── op_fsync.c ├── op_getattr.c ├── op_getxattr.c ├── op_init.c ├── op_link.c ├── op_mkdir.c ├── op_mknod.c ├── op_open.c ├── op_read.c ├── op_readdir.c ├── op_readlink.c ├── op_release.c ├── op_rename.c ├── op_rmdir.c ├── op_statfs.c ├── op_symlink.c ├── op_truncate.c ├── op_unlink.c ├── op_utimens.c └── op_write.c └── tools ├── Makefile.am └── macosx ├── Description.plist ├── Info.plist.in ├── Install_resources ├── .VolumeIcon.icns ├── Authors.rtf ├── ChangeLog.rtf ├── English.lproj │ ├── InstallationCheck.strings │ └── VolumeCheck.strings ├── InstallationCheck ├── InstallationCheck.strings ├── License.rtf ├── README.rtf ├── VolumeCheck ├── VolumeCheck.strings ├── Welcome.rtf └── background.tiff ├── Makefile.am ├── fuse-ext2.fs ├── Contents │ ├── Info.plist.in │ ├── PkgInfo │ └── Resources │ │ ├── English.lproj │ │ └── InfoPlist.strings │ │ └── mount_fuse-ext2 └── fuse-ext2.util ├── make-pkg.sh └── prefpane ├── English.lproj ├── InfoPlist.strings └── fuse_ext2Pref.xib ├── Info.plist ├── fuse-ext2.xcodeproj ├── anhanguera.mode1v3 ├── anhanguera.pbxuser └── project.pbxproj ├── fuse-ext2_Prefix.pch ├── fuse_ext2Pref.h ├── fuse_ext2Pref.m └── penguin.png /.gitignore: -------------------------------------------------------------------------------- 1 | .cproject 2 | .project 3 | fs.ext2 4 | 5 | # IDE: PhpStorm 6 | .idea 7 | # VSCODE 8 | .vscode 9 | 10 | # Ignore the below build artifacts from running... 11 | # `autogen.sh` 12 | # in the project root 13 | Makefile.in 14 | aclocal.m4 15 | ar-lib 16 | autom4te.cache/ 17 | compile 18 | config.log 19 | config.guess 20 | config.h.in 21 | config.sub 22 | configure 23 | depcomp 24 | fuse-ext2/Makefine.in 25 | install-sh 26 | ltmain.sh 27 | missing 28 | tools/Makefile.in 29 | tools/macosx/Makefile.in 30 | 31 | # Ingore artifacts created by running... 32 | # 33 | # env CFLAGS="-idirafter/opt/gnu/include -idirafter/usr/local/include/osxfuse/" LDFLAGS="-L/opt/gnu/lib -L/usr/local//lib" ./configure 34 | ## 35 | Makefile 36 | config.h 37 | config.status 38 | fuse-ext2.pc 39 | fuse-ext2/.deps/ 40 | fuse-ext2/Makefile 41 | libtool 42 | stamp-h1 43 | tools/Makefile 44 | tools/macosx/Makefile 45 | 46 | # Ignore build artifacts when running `make` with the project root 47 | ## 48 | # NOTE: all object files, ie. `.o`'s are placed within `fuse-ext2/fuse-ext2` dir 49 | ## 50 | **/fuse-ext2 51 | tools/macosx/prefpane/build 52 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | 2 | Alper Akcan 3 | Renzo Davoli 4 | 5 | - Contributors (in name order) 6 | 7 | Sanchez Guido 8 | Sven Gustafsson 9 | Erik Larsson 10 | Dave Vasilevsky 11 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Mon 15 Jan 2024 02:02:58 AM +03 2 | - version 0.0.11 3 | - default mount options is always ro 4 | - reverted some missed pull request commits 5 | 6 | Mon Mar 30 19:17:44 EEST 2015 7 | - version 0.0.9 8 | - fix write tests for pjdfstest 9 | - fix ext2fs_file_*, need to open/release in every file operation 10 | 11 | Mon Mar 28 10:21:43 EEST 2015 12 | - version 0.0.8 - lazarus, raised from dead 13 | - use e2fsprogs from system (mac, linux) 14 | - fix build routines for new systems (mac, linux) 15 | - switch to osxfuse (mac) 16 | 17 | Wed 30 Dec 2009 04:17:02 EET 18 | - enable noappledouble only for readonly mode by default 19 | 20 | Thu 24 Dec 2009 14:40:10 EET 21 | - version 0.0.7 22 | 23 | Tue 03 Nov 2009 04:02:06 AM EEST 24 | - get device volume name in probe stage. now diskutil shows volume name 25 | on device bar, as a result device mount point is created as 26 | '/Volumes/${volume_name}'. 27 | - supports mac osx 10.6 in compatibility mode. 28 | 29 | Fri 09 Oct 2009 12:53:02 AM EEST 30 | - fixed big file support (write > 4G) 31 | 32 | Tue 29 Sep 2009 05:25:08 AM EEST 33 | - improved probe time (mount time improved %50) 34 | - improved mount time for read-only mode 35 | - mount time reduced from ~8 secs to ~2 secs 36 | - added windows_fat_(16/32) partition type to probe types 37 | - added 0.0.6 md5sum to release.xml 38 | - added release-beta.xml, just like macfuse 39 | - linux fs type probe decreased from 50 to 3500 40 | - disabled apple double files 41 | 42 | Wed 23 Sep 2009 00:15:10 AM EEST 43 | - version 0.0.6 44 | - fixed big file support for size > 4Gb 45 | - prefpane supports uninstall/update 46 | 47 | Mon 07 Sep 2009 00:02:40 AM EEST 48 | - added fuse-ext2.1 man page written by Renzo 49 | 50 | Wed 02 Sep 2009 07:43:48 PM EEST 51 | - merge in renzo branch rev.140 including: 52 | - support of file truncate 53 | - support of concurrent file access 54 | - view-os compatibility (see wiki.virtualsquare.org, umfuse) 55 | 56 | Mon 22 Jun 2009 05:36:45 PM EEST 57 | - uninstall support for mac 58 | - initial updater for mac 59 | 60 | Thu 11 Jun 2009 10:55:23 PM EEST 61 | - set version information at compile time for info.plist 62 | - corrected mke2fs path information in make-pkg.sh 63 | 64 | Tue 09 Jun 2009 02:09:15 AM EEST 65 | - upgrade to e2fsprogs-1.41.6 66 | 67 | Mon 08 Jun 2009 12:47:59 AM EEST 68 | - added uuid lib 69 | 70 | Wed 3 Jun 2009 07:09:27 PM EEST 71 | - version 0.0.5 72 | - updated authors file 73 | - minor directory changes 74 | 75 | Tue 2 Jun 2009 05:04:49 PM EEST 76 | - big/little endian support for universal build 77 | 78 | Tue 2 Jun 2009 00:39:06 AM EEST 79 | - upgrade to e2fsprogs 1.41.5 80 | - added mke2fs for disk format 81 | - added format support to diskutil 82 | 83 | Wed 27 May 2009 03:11:38 AM EEST 84 | - 10.4 tiger build instructions added to README 85 | - added /usr/local/[lib,include] to fuse-ext2 86 | compile flags. 87 | 88 | Tue 19 May 2009 07:34:23 PM EEST 89 | - version 0.0.4 90 | - get etx2 label in probe stage 91 | - make labeling work for universal build, also 92 | 93 | Tue 21 Apr 2009 02:32:57 PM EEST 94 | - merge in Dave Vasilevsky's labels patch 95 | 96 | Sat 04 Apr 2009 02:28:34 AM EET 97 | - disable multithread 98 | - reduce wait time to 5 seconds 99 | 100 | Mon 09 Feb 2009 04:42:51 PM EET 101 | - mac osx file system bundle support 102 | - automount support 103 | - first 'real' stable (read only) 104 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | SUBDIRS = 3 | SUBDIRS += fuse-ext2 4 | SUBDIRS += tools 5 | 6 | EXTRA_DIST = \ 7 | fuse-ext2.pc.in 8 | 9 | pkgconfigdir = @pkgconfigdir@ 10 | pkgconfig_DATA = fuse-ext2.pc 11 | 12 | $(pkgconfig_DATA): config.status 13 | 14 | man1_MANS = fuse-ext2.1 15 | 16 | if DARWIN 17 | package: 18 | $(SHELL) $(top_srcdir)/tools/macosx/make-pkg.sh "$(VERSION)" "$(top_builddir)" "$(top_srcdir)/tools/macosx/" 19 | endif 20 | if LINUX 21 | package: 22 | echo "You can use checkinstall or some other equivalent tool to generate install package for your distribution." 23 | endif 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fuse Ext2 2 | 3 | **Fuse-ext2** is an EXT2/EXT3/EXT4 filesystem for [**FUSE**](https://github.com/osxfuse/fuse), and is built to work with [**osxfuse**](https://github.com/osxfuse/osxfuse). 4 | 5 | ## Dependencies 6 | 7 | **Fuse-ext2** requires at least Fuse version 2.6.0 for Linux. 8 | **Fuse-ext2** requires at least **Fuse for macOS** version 2.7.5 or greater. 9 | 10 | - Linux: [Fuse](http://fuse.sourceforge.net/) 11 | - macOS: [Fuse for macOS](https://osxfuse.github.io) 12 | 13 | ### Alternate Install method of _Fuse for macOS_ 14 | 15 | **Fuse for macOS** can be installed via [homebrew](http://brew.sh) if [Homebrew-Cask](https://caskroom.github.io/) has been tapped. 16 | 17 | Look for **`homebrew/cask`** in the output. 18 | 19 | To install **Fuse for macOS** using brew: 20 | 21 | You will be interactively prompted for sudo access during the install. 22 | 23 | ```bash 24 | brew install --cask osxfuse 25 | ``` 26 | 27 | For Fuse version 4.0.0 and higher use macfuse 28 | 29 | ```bash 30 | brew install --cask macfuse 31 | ``` 32 | 33 | ## Building 34 | 35 | ### Debian/Ubuntu: 36 | 37 | Building from source depends on the following: 38 | 39 | * m4 40 | * autoconf 41 | * automake 42 | * libtool 43 | * libfuse-dev 44 | * e2fsprogs 45 | * comerr-dev 46 | * e2fslibs-dev 47 | 48 | ```shell 49 | $ sudo apt-get install m4 autoconf automake libtool 50 | $ sudo apt-get install libfuse-dev e2fsprogs comerr-dev e2fslibs-dev 51 | 52 | $ ./autogen.sh 53 | $ ./configure 54 | $ make 55 | $ sudo make install 56 | ``` 57 | 58 | ### Fedora 59 | ```bash 60 | $ sudo dnf install @development-tools m4 autoconf automake libtool e2fsprogs libcom_err-devel fuse-libs e2fsprogs-devel fuse-devel 61 | # build part 62 | $ ./autogen.sh 63 | $ ./configure 64 | $ make 65 | $ sudo make install 66 | ``` 67 | 68 | You can use `checkinstall` or some other equivalent tool to generate an install 69 | package for your distribution. 70 | 71 | ### FreeBSD: 72 | 73 | Install via pkg: 74 | 75 | ```shell 76 | $ pkg install sysutils/fusefs-ext2 77 | ``` 78 | 79 | Building via ports: 80 | 81 | ```shell 82 | $ cd /usr/ports/sysutils/fusefs-ext2 83 | $ make install clean 84 | ``` 85 | 86 | ### macOS: 87 | 88 | Dependencies: 89 | 90 | [OSXfuse](https://osxfuse.github.io) 91 | 92 | Building **from source** depends on the following: 93 | 94 | * m4 95 | * autoconf 96 | * automake 97 | * libtool 98 | * e2fsprogs 99 | * xcode-select 100 | 101 | Copy and paste this into a file such as `/tmp/ext4/script.sh`, but do *not* name the file `install.sh`. Remember to `chmod +x script.sh`. Run it 102 | from that directory - `./script.sh` 103 | 104 | ```shell 105 | #!/bin/sh 106 | export PATH=/opt/gnu/bin:$PATH 107 | export PKG_CONFIG_PATH=/opt/gnu/lib/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH 108 | 109 | mkdir fuse-ext2.build 110 | cd fuse-ext2.build 111 | 112 | if [ ! -d fuse-ext2 ]; then 113 | git clone https://github.com/alperakcan/fuse-ext2.git 114 | fi 115 | 116 | # m4 117 | if [ ! -f m4-1.4.17.tar.gz ]; then 118 | curl -O -L http://ftp.gnu.org/gnu/m4/m4-1.4.17.tar.gz 119 | fi 120 | tar -zxvf m4-1.4.17.tar.gz 121 | cd m4-1.4.17 122 | ./configure --prefix=/opt/gnu 123 | make -j 16 124 | sudo make install 125 | cd ../ 126 | 127 | # autoconf 128 | if [ ! -f autoconf-2.69.tar.gz ]; then 129 | curl -O -L http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz 130 | fi 131 | tar -zxvf autoconf-2.69.tar.gz 132 | cd autoconf-2.69 133 | ./configure --prefix=/opt/gnu 134 | make 135 | sudo make install 136 | cd ../ 137 | 138 | # automake 139 | if [ ! -f automake-1.15.tar.gz ]; then 140 | curl -O -L http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz 141 | fi 142 | tar -zxvf automake-1.15.tar.gz 143 | cd automake-1.15 144 | ./configure --prefix=/opt/gnu 145 | make 146 | sudo make install 147 | cd ../ 148 | 149 | # libtool 150 | if [ ! -f libtool-2.4.6.tar.gz ]; then 151 | curl -O -L http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz 152 | fi 153 | tar -zxvf libtool-2.4.6.tar.gz 154 | cd libtool-2.4.6 155 | ./configure --prefix=/opt/gnu 156 | make 157 | sudo make install 158 | cd ../ 159 | 160 | # e2fsprogs 161 | if [ ! -f e2fsprogs-1.43.4.tar.gz ]; then 162 | curl -O -L https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/v1.43.4/e2fsprogs-1.43.4.tar.gz 163 | fi 164 | tar -zxvf e2fsprogs-1.43.4.tar.gz 165 | cd e2fsprogs-1.43.4 166 | ./configure --prefix=/opt/gnu --disable-nls 167 | make 168 | sudo make install 169 | sudo make install-libs 170 | sudo cp /opt/gnu/lib/pkgconfig/* /usr/local/lib/pkgconfig 171 | cd ../ 172 | 173 | # fuse-ext2 174 | export PATH=/opt/gnu/bin:$PATH 175 | export PKG_CONFIG_PATH=/opt/gnu/lib/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH 176 | 177 | cd fuse-ext2 178 | ./autogen.sh 179 | CFLAGS="-idirafter/opt/gnu/include -idirafter/usr/local/include/osxfuse/" LDFLAGS="-L/opt/gnu/lib -L/usr/local/lib" ./configure 180 | make 181 | sudo make install 182 | ``` 183 | 184 | # Test 185 | 186 | The e2fsprogs live in /opt/gnu/bin and /opt/gnu/sbin. fuse-ext2 is in /usr/local/bin. 187 | 188 | ```shell 189 | cd 190 | dd if=/dev/zero of=/tmp/test-fs.ext4 bs=1024 count=102400 191 | /opt/gnu/sbin/mkfs.ext4 /tmp/test-fs.ext4 192 | mkdir -p ~/mnt/fuse-ext2.test-fs.ext4 193 | fuse-ext2 /tmp/test-fs.ext4 ~/mnt/fuse-ext2.test-fs.ext4 -o rw+,allow_other,uid=501,gid=20 194 | ``` 195 | 196 | To verify the **UID** and **GID** of the user mounting the file system: 197 | 198 | ```shell 199 | id 200 | ``` 201 | 202 | To verify the file system has mounted properly: 203 | 204 | ```shell 205 | mount 206 | ``` 207 | 208 | # Usage 209 | 210 | See the [Man page](http://man.cx/fuseext2(1)) for options. 211 | 212 | ``` 213 | Usage: fuse-ext2 [-o option[,...]] 214 | 215 | Options: ro, rw+, force, allow_other 216 | Please see details in the manual. 217 | 218 | Example: fuse-ext2 /dev/sda1 /mnt/sda1 219 | ``` 220 | 221 | # Bugs 222 | 223 | * Multithread support is broken for now, so fuse operates in a single thread. 224 | * There are no known bugs for read-only mode, read only mode should be ok for everyone. 225 | * Even though write support is available, _please do not mount your filesystems with write support unless you have nothing to lose._ 226 | 227 | Please send the output of the command below when reporting bugs as a [GitHub Issue](https://github.com/alperakcan/fuse-ext2/issues/new). 228 | Before submitting a bug report, please look at the [existing issues](https://github.com/alperakcan/fuse-ext2/issues?utf8=%E2%9C%93&q=is%3Aissue) first. 229 | 230 | ```shell 231 | $ /usr/local/bin/fuse-ext2 -v /dev/path /mnt/point -o debug 232 | ``` 233 | 234 | # Important: Partition Labels 235 | 236 | Please **do not** use commas `,` in partition labels. 237 | 238 | **Wrong:** `e2label /dev/disk0s3 "linux,ext3"` 239 | 240 | **Correct:** `e2label /dev/disk0s3 "linux-ext3"` 241 | 242 | # Contact 243 | 244 | Alper Akcan 245 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to generate configure, Makefile.in's, etc 3 | 4 | (autoreconf --version) < /dev/null > /dev/null 2>&1 || { 5 | (autoconf --version) < /dev/null > /dev/null 2>&1 || { 6 | echo 7 | echo "**Error**: You must have the GNU Build System (autoconf, automake, " 8 | echo "libtool, etc) to update the build system. Download the appropriate" 9 | echo "packages for your distribution, or get the source tar balls from" 10 | echo "ftp://ftp.gnu.org/pub/gnu/." 11 | exit 1 12 | } 13 | echo 14 | echo "**Error**: Your version of autoconf is too old (you need at least 2.57)" 15 | echo "to update the build system. Download the appropriate updated package" 16 | echo "for your distribution, or get the source tar ball from" 17 | echo "ftp://ftp.gnu.org/pub/gnu/." 18 | exit 1 19 | } 20 | 21 | echo Running autoreconf --verbose --install --force 22 | autoreconf --verbose --install --force 23 | 24 | echo Removing autom4te.cache 25 | rm -rf autom4te.cache 26 | 27 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | 2 | AC_INIT([fuse-ext2], [0.0.11], [alper.akcan@gmail.com]) 3 | AC_CANONICAL_TARGET 4 | AM_INIT_AUTOMAKE([-Wall -Werror foreign]) 5 | AC_CONFIG_HEADER([config.h]) 6 | 7 | # Checks for programs. 8 | AC_PROG_CXX 9 | AC_PROG_AWK 10 | AC_PROG_CC 11 | AC_PROG_INSTALL 12 | m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) 13 | m4_ifdef([AC_PROG_LIB],[AC_PROG_LIB],[m4_warn(portability,[Missing AC_PROJ_LIB])]) 14 | AC_PROG_OBJC 15 | AC_PROG_LIBTOOL 16 | AC_PATH_PROG(CHMOD, chmod, :) 17 | 18 | case $target_os in 19 | *linux*) arch=linux;; 20 | *darwin*) arch=darwin;; 21 | *) arch=unknown;; 22 | esac 23 | 24 | # Large file support 25 | AC_TYPE_SIZE_T 26 | AC_TYPE_OFF_T 27 | AC_DEFINE([_LARGE_FILE_SOURCE], [], [Large files support]) 28 | AC_DEFINE([_FILE_OFFSET_BITS], [64], [File Offset size]) 29 | 30 | # Checks for header files. 31 | AC_HEADER_DIRENT 32 | AC_HEADER_STDC 33 | AC_HEADER_MAJOR 34 | AC_CHECK_HEADERS([ \ 35 | fcntl.h \ 36 | malloc.h \ 37 | mntent.h \ 38 | netinet/in.h \ 39 | paths.h \ 40 | stddef.h \ 41 | stdlib.h \ 42 | string.h \ 43 | linux/fd.h \ 44 | sys/file.h \ 45 | sys/ioctl.h \ 46 | sys/mount.h \ 47 | sys/param.h \ 48 | sys/statvfs.h \ 49 | sys/time.h \ 50 | sys/types.h \ 51 | sys/stat.h \ 52 | sys/mkdev.h \ 53 | sys/ioctl.h \ 54 | sys/syscall.h \ 55 | sys/resource.h \ 56 | sys/mman.h \ 57 | sys/prctl.h \ 58 | sys/disklabel.h \ 59 | sys/queue.h \ 60 | sys/socket.h \ 61 | sys/un.h \ 62 | sys/sockio.h \ 63 | net/if.h \ 64 | netinet/in.h \ 65 | net/if_dl.h \ 66 | errno.h \ 67 | unistd.h \ 68 | utime.h \ 69 | getopt.h \ 70 | inttypes.h \ 71 | ]) 72 | 73 | AC_CHECK_HEADERS(sys/disk.h sys/mount.h,,, 74 | [[ 75 | #if HAVE_SYS_QUEUE_H 76 | #include 77 | #endif 78 | ]]) 79 | 80 | # Checks for typedefs, structures, and compiler characteristics. 81 | AC_C_CONST 82 | AC_C_INLINE 83 | AC_TYPE_MODE_T 84 | AC_TYPE_OFF_T 85 | AC_TYPE_SIZE_T 86 | AC_TYPE_SSIZE_T 87 | AC_CHECK_MEMBERS([struct stat.st_blksize]) 88 | AC_STRUCT_ST_BLOCKS 89 | AC_CHECK_MEMBERS([struct stat.st_rdev]) 90 | AC_HEADER_TIME 91 | AC_CHECK_DECL(llseek,[AC_DEFINE(HAVE_LLSEEK_PROTOTYPE, 1, [Define to 1 if you have the `llseek' prototype.])],, 92 | [#include ]) 93 | AC_CHECK_DECL(lseek64,[AC_DEFINE(HAVE_LSEEK64_PROTOTYPE, 1, [Define to 1 if you have the `lseek64' prototype.])],, 94 | [#define _LARGEFILE_SOURCE 95 | #define _LARGEFILE64_SOURCE 96 | #include ]) 97 | 98 | dnl Check to see if ssize_t was decleared 99 | AC_CHECK_TYPE(ssize_t,[AC_DEFINE(HAVE_TYPE_SSIZE_T, 1, [Define to 1 if you have the `ssize_t' prototype.])],, 100 | [#include ]) 101 | 102 | # Checks for library functions. 103 | AC_FUNC_VPRINTF 104 | AC_FUNC_CHOWN 105 | AC_FUNC_CLOSEDIR_VOID 106 | AC_FUNC_GETMNTENT 107 | AC_PROG_GCC_TRADITIONAL 108 | AC_FUNC_MALLOC 109 | AC_FUNC_MEMCMP 110 | AC_FUNC_MMAP 111 | AC_FUNC_REALLOC 112 | AC_FUNC_SELECT_ARGTYPES 113 | AC_FUNC_STAT 114 | AC_FUNC_UTIME_NULL 115 | AC_CHECK_FUNCS([ \ 116 | ftruncate \ 117 | getmntent \ 118 | getmntinfo \ 119 | getpagesize \ 120 | hasmntopt \ 121 | memmove \ 122 | memset \ 123 | munmap \ 124 | random \ 125 | select \ 126 | srand \ 127 | srandom \ 128 | strcasecmp \ 129 | strchr \ 130 | strdup \ 131 | strerror \ 132 | strrchr \ 133 | strtol \ 134 | strtoul \ 135 | strtoull \ 136 | uname \ 137 | utime \ 138 | llseek \ 139 | lseek64 \ 140 | ]) 141 | 142 | # Checks for libraries 143 | AC_SEARCH_LIBS([sem_post], [pthread], [], [AC_MSG_ERROR([Can't find pthreads, please install it])]) 144 | AC_SEARCH_LIBS([fuse_main], [osxfuse fuse], [], [AC_MSG_ERROR([Can't find libfuse, please install it])]) 145 | AC_SEARCH_LIBS([com_err], [com_err], [], [AC_MSG_ERROR([Can't find comerr, please install it])]) 146 | AC_SEARCH_LIBS([ext2fs_open], [ext2fs], [], [AC_MSG_ERROR([Can't find e2fslibs, please install it])]) 147 | 148 | AC_MSG_CHECKING([if FUSE on this system is too new for us]) 149 | AC_EGREP_CPP([fuse_version_yes], [ 150 | #define _FILE_OFFSET_BITS 64 151 | #define FUSE_USE_VERSION 27 152 | #include "fuse.h" 153 | #if FUSE_VERSION > 27 154 | fuse_version_yes 155 | #endif 156 | ], AC_DEFINE([FUSE_USE_VERSION], [27], [Version of FUSE interface]) AC_MSG_RESULT([yes]), 157 | AC_DEFINE([FUSE_USE_VERSION], [FUSE_VERSION], [Version of FUSE interface]) AC_MSG_RESULT([no])) 158 | 159 | # Check extra parameters 160 | AC_ARG_ENABLE([debug], 161 | [ --enable-debug enable noisy debug], 162 | if test "$enableval" = "no" 163 | then 164 | DEBUG_CMT=# 165 | echo "Disabling debug support" 166 | else 167 | DEBUG_CMT= 168 | AC_DEFINE(ENABLE_DEBUG, 1, [Define to 1 if you want 'debug' support.]) 169 | echo "Enabling debug support" 170 | fi 171 | , 172 | DEBUG_CMT= 173 | echo "Disabling debug support by default" 174 | AC_DEFINE(ENABLE_DEBUG, 0, [Define to 1 if you want 'debug' support.]) 175 | ) 176 | 177 | AC_ARG_WITH(pkgconfigdir, 178 | [ --with-pkgconfigdir=DIR pkgconfig file in DIR @<:@LIBDIR/pkgconfig@:>@], 179 | [pkgconfigdir=$withval], 180 | [pkgconfigdir='${libdir}/pkgconfig']) 181 | AC_SUBST(pkgconfigdir) 182 | 183 | AM_CONDITIONAL(LINUX, test "$arch" = linux) 184 | AM_CONDITIONAL(DARWIN, test "$arch" = darwin) 185 | 186 | AC_CONFIG_FILES([ 187 | fuse-ext2.pc 188 | Makefile 189 | fuse-ext2/Makefile 190 | tools/Makefile 191 | tools/macosx/Makefile 192 | ]) 193 | 194 | AC_OUTPUT 195 | -------------------------------------------------------------------------------- /fuse-ext2.1: -------------------------------------------------------------------------------- 1 | .TH FUSE-EXT2 "1" "September 2009" "FUSE/UMFUSE modules" "User Commands" 2 | .SH NAME 3 | FUSE-EXT2 \- FUSE module for Second Extended File System 4 | .SH SYNOPSIS 5 | .B fuse-ext2 6 | .RI [ OPTION ]...\& 7 | .I imagefile mountpoint 8 | .LP 9 | .B fuse-ext2 10 | .I imagefile mountpoint 11 | .RI [ OPTION ]... 12 | .SH DESCRIPTION 13 | Fuse-ext2 mounts an ext2/ext3/ext4 partition or image file. It uses Fuse support 14 | (Filesystem in Userspace) included in modern Linux kernels. 15 | The same module is available for view-os (umview(1), kmview(1)) under 16 | the name \fBumfuseext2\fR. 17 | .SH OPTIONS 18 | .SS "General options" 19 | .TP 20 | \fB\-o\fR opt,[opt...] 21 | mount options 22 | .TP 23 | \fB\-h\fR \fB\-\-help\fR 24 | print help 25 | .TP 26 | \fB\-V\fR \fB\-\-version\fR 27 | print version 28 | .SS "FUSE-EXT2 options:" 29 | .TP 30 | \fB\-o\fR force 31 | force read-write mount (\fBEXPERIMENTAL\fR, the option \fBrw\fR without \fBforce\fR 32 | mounts the file system in read-only mode, with a warning). 33 | .TP 34 | \fB\-o\fR rw+ 35 | enable read-write mount (\fBEXPERIMENTAL\fR, is a shortcut for -o rw,force) 36 | .SS "FUSE options:" 37 | 38 | .TP 39 | \fB\-d, \-o debug\fR 40 | enable debug output (implies \fB\-f\fR) 41 | .TP 42 | \fB\-f\fR 43 | foreground operation 44 | .TP 45 | \fB\-s\fR 46 | disable multi\-threaded operation 47 | .TP 48 | \fB\-o allow_other\fR 49 | allow access to other users 50 | .TP 51 | \fB\-o allow_root\fR 52 | allow access to root 53 | .TP 54 | \fB\-o nonempty\fR 55 | allow mounts over non\-empty file/dir 56 | .TP 57 | \fB\-o default_permissions\fR 58 | enable permission checking by kernel 59 | .TP 60 | \fB\-o fsname=\fINAME\fR 61 | set filesystem name 62 | .TP 63 | \fB\-o large_read\fR 64 | issue large read requests (2.4 only) 65 | .TP 66 | \fB\-o max_read=\fIN\fR 67 | set maximum size of read requests 68 | .TP 69 | \fB\-o hard_remove\fR 70 | immediate removal (don't hide files) 71 | .TP 72 | \fB\-o use_ino\fR 73 | let filesystem set inode numbers 74 | .TP 75 | \fB\-o readdir_ino\fR 76 | try to fill in d_ino in readdir 77 | .TP 78 | \fB\-o direct_io\fR 79 | use direct I/O 80 | .TP 81 | \fB\-o kernel_cache\fR 82 | cache files in kernel 83 | .TP 84 | \fB\-o [no]auto_cache\fR 85 | enable caching based on modification times 86 | .TP 87 | \fB\-o umask=\fIM\fR 88 | set file permissions (octal) 89 | .TP 90 | \fB\-o uid=\fIN\fR 91 | set file owner 92 | .TP 93 | \fB\-o gid=\fIN\fR 94 | set file group 95 | .TP 96 | \fB\-o entry_timeout=\fIT\fR 97 | cache timeout for names (1.0s) 98 | .TP 99 | \fB\-o negative_timeout=\fIT\fR 100 | cache timeout for deleted names (0.0s) 101 | .TP 102 | \fB\-o attr_timeout=\fIT\fR 103 | cache timeout for attributes (1.0s) 104 | .TP 105 | \fB\-o ac_attr_timeout=\fIT\fR 106 | auto cache timeout for attributes (attr_timeout) 107 | .TP 108 | \fB\-o intr\fR 109 | allow requests to be interrupted 110 | .TP 111 | \fB\-o intr_signal=\fINUM\fR 112 | signal to send on interrupt (10) 113 | .TP 114 | \fB\-o max_write=\fIN\fR 115 | set maximum size of write requests 116 | .TP 117 | \fB\-o max_readahead=\fIN\fR 118 | set maximum readahead 119 | .TP 120 | \fB\-o async_read\fR 121 | perform reads asynchronously (default) 122 | .TP 123 | \fB\-o sync_read\fR 124 | perform reads synchronously 125 | .SH AUTHORS 126 | .TP 127 | Alper Akcan 128 | .TP 129 | Renzo Davoli 130 | .TP 131 | See \fIhttp://github.com/alperkacan/fuse-ext2/, http://www.virtualsquare.org\fR. 132 | -------------------------------------------------------------------------------- /fuse-ext2.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: fuse-ext2 7 | Description: EXT2/EXT3/EXT4 File System support for FUSE 8 | Version: @VERSION@ 9 | -------------------------------------------------------------------------------- /fuse-ext2/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | DEVELFLAGS = 3 | 4 | bin_PROGRAMS = \ 5 | fuse-ext2 \ 6 | fuse-ext2.probe 7 | 8 | if LINUX 9 | moddir = $(libdir)/umview/modules 10 | mod_LTLIBRARIES = umfuseext2.la 11 | endif 12 | 13 | fuse_ext2_probe_SOURCES = \ 14 | fuse-ext2.h \ 15 | fuse-ext2.probe.c \ 16 | do_probe.c 17 | 18 | fuse_ext2_probe_CFLAGS = \ 19 | -Wall \ 20 | -DHAVE_CONFIG_H \ 21 | -I/usr/local/include 22 | 23 | fuse_ext2_SOURCES = \ 24 | fuse-ext2.h \ 25 | fuse-ext2.c \ 26 | do_probe.c \ 27 | do_check.c \ 28 | do_fillstatbuf.c \ 29 | do_readinode.c \ 30 | do_writeinode.c \ 31 | do_killfilebyinode.c \ 32 | op_init.c \ 33 | op_destroy.c \ 34 | op_access.c \ 35 | op_fgetattr.c \ 36 | op_getattr.c \ 37 | op_getxattr.c \ 38 | op_open.c \ 39 | op_read.c \ 40 | op_readdir.c \ 41 | op_readlink.c \ 42 | op_release.c \ 43 | op_statfs.c \ 44 | op_chown.c \ 45 | op_chmod.c \ 46 | op_create.c \ 47 | op_flush.c \ 48 | op_fsync.c \ 49 | op_mkdir.c \ 50 | op_rmdir.c \ 51 | op_unlink.c \ 52 | op_utimens.c \ 53 | op_write.c \ 54 | op_mknod.c \ 55 | op_symlink.c \ 56 | op_truncate.c \ 57 | op_link.c \ 58 | op_rename.c 59 | 60 | umfuseext2_la_SOURCES = \ 61 | fuse-ext2.h \ 62 | fuse-ext2.c \ 63 | do_probe.c \ 64 | do_check.c \ 65 | do_fillstatbuf.c \ 66 | do_readinode.c \ 67 | do_writeinode.c \ 68 | do_killfilebyinode.c \ 69 | op_init.c \ 70 | op_destroy.c \ 71 | op_access.c \ 72 | op_fgetattr.c \ 73 | op_getattr.c \ 74 | op_getxattr.c \ 75 | op_open.c \ 76 | op_read.c \ 77 | op_readdir.c \ 78 | op_readlink.c \ 79 | op_release.c \ 80 | op_statfs.c \ 81 | op_chown.c \ 82 | op_chmod.c \ 83 | op_create.c \ 84 | op_flush.c \ 85 | op_fsync.c \ 86 | op_mkdir.c \ 87 | op_rmdir.c \ 88 | op_unlink.c \ 89 | op_utimens.c \ 90 | op_write.c \ 91 | op_mknod.c \ 92 | op_symlink.c \ 93 | op_truncate.c \ 94 | op_link.c \ 95 | op_rename.c 96 | 97 | umfuseext2_la_CFLAGS = \ 98 | -Wall \ 99 | -DHAVE_CONFIG_H \ 100 | -D_GNU_SOURCE \ 101 | $(DEVELFLAGS) \ 102 | -I$(includedir)/umview \ 103 | -I/usr/local/include 104 | 105 | umfuseext2_la_LDFLAGS = \ 106 | -module \ 107 | -avoid-version \ 108 | -export-dynamic \ 109 | -lext2fs 110 | 111 | fuse_ext2_CFLAGS = \ 112 | -Wall \ 113 | -DHAVE_CONFIG_H \ 114 | -I/usr/local/include 115 | 116 | if DARWIN 117 | bin_PROGRAMS += \ 118 | fuse-ext2.wait \ 119 | fuse-ext2.install \ 120 | fuse-ext2.uninstall 121 | 122 | fuse_ext2_wait_SOURCES = \ 123 | fuse-ext2.wait.m 124 | 125 | fuse_ext2_wait_CFLAGS = \ 126 | -Wall \ 127 | -D__FreeBSD__=10 128 | 129 | fuse_ext2_wait_LDFLAGS = \ 130 | -framework CoreFoundation 131 | 132 | fuse_ext2_install_SOURCES = \ 133 | fuse-ext2.install.m 134 | 135 | fuse_ext2_install_CFLAGS = \ 136 | -ObjC 137 | 138 | fuse_ext2_install_LDFLAGS = \ 139 | -framework Foundation 140 | 141 | fuse_ext2_uninstall_SOURCES = \ 142 | fuse-ext2.uninstall.m 143 | 144 | fuse_ext2_probe_CFLAGS += \ 145 | -D__FreeBSD__=10 146 | 147 | fuse_ext2_CFLAGS += \ 148 | -D__FreeBSD__=10 149 | endif 150 | 151 | if DARWIN 152 | install-exec-local: 153 | $(INSTALL) -d "$(DESTDIR)/$(sbindir)" 154 | $(LN_S) -f "/Library/Filesystems/fuse-ext2.fs/Contents/Resources/mount_fuse-ext2" "$(DESTDIR)/$(sbindir)/mount_fuse-ext2" 155 | $(LN_S) -f "/usr/local/opt/e2fsprogs/sbin/e2label" "$(DESTDIR)/$(sbindir)/e2label" 156 | $(LN_S) -f "/usr/local/opt/e2fsprogs/sbin/mke2fs" "$(DESTDIR)/$(sbindir)/mke2fs" 157 | endif 158 | if LINUX 159 | install-data-hook: 160 | cd "$(DESTDIR)/$(moddir)" && rm -f $(mod_LTLIBRARIES) 161 | 162 | install-exec-local: 163 | $(INSTALL) -d "$(DESTDIR)/$(sbindir)" 164 | $(LN_S) -f "$(bindir)/fuse-ext2" "$(DESTDIR)/$(sbindir)/mount.fuse-ext2" 165 | endif 166 | -------------------------------------------------------------------------------- /fuse-ext2/do_check.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int do_check (const char *path) 24 | { 25 | char *basename_path; 26 | basename_path = strrchr(path, '/'); 27 | if (basename_path == NULL) { 28 | debugf("this should not happen %s", path); 29 | return -ENOENT; 30 | } 31 | basename_path++; 32 | if (strlen(basename_path) > 255) { 33 | debugf("basename exceeds 255 characters %s",path); 34 | return -ENAMETOOLONG; 35 | } 36 | return 0; 37 | } 38 | 39 | int do_check_split (const char *path, char **dirname, char **basename) 40 | { 41 | char *tmp; 42 | char *cpath = strdup(path); 43 | tmp = strrchr(cpath, '/'); 44 | if (tmp == NULL) { 45 | debugf("this should not happen %s", path); 46 | free(cpath); 47 | return -ENOENT; 48 | } 49 | *tmp='\0'; 50 | tmp++; 51 | if (strlen(tmp) > 255) { 52 | debugf("basename exceeds 255 characters %s",path); 53 | free(cpath); 54 | return -ENAMETOOLONG; 55 | } 56 | *dirname = cpath; 57 | *basename = tmp; 58 | return 0; 59 | } 60 | 61 | void free_split (char *dirname, char *basename) 62 | { 63 | free(dirname); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /fuse-ext2/do_fillstatbuf.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | static inline dev_t old_decode_dev (__u16 val) 24 | { 25 | return makedev((val >> 8) & 255, val & 255); 26 | } 27 | 28 | static inline dev_t new_decode_dev (__u32 dev) 29 | { 30 | unsigned major = (dev & 0xfff00) >> 8; 31 | unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00); 32 | return makedev(major, minor); 33 | } 34 | 35 | void do_fillstatbuf (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode, struct stat *st) 36 | { 37 | debugf("enter"); 38 | memset(st, 0, sizeof(*st)); 39 | /* XXX workaround 40 | * should be unique and != existing devices */ 41 | st->st_dev = (dev_t) ((long) e2fs); 42 | st->st_ino = ino; 43 | st->st_mode = inode->i_mode; 44 | st->st_nlink = inode->i_links_count; 45 | st->st_uid = ext2_read_uid(inode); 46 | st->st_gid = ext2_read_gid(inode); 47 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { 48 | if (inode->i_block[0]) { 49 | st->st_rdev = old_decode_dev(ext2fs_le32_to_cpu(inode->i_block[0])); 50 | } else { 51 | st->st_rdev = new_decode_dev(ext2fs_le32_to_cpu(inode->i_block[1])); 52 | } 53 | } else { 54 | st->st_rdev = 0; 55 | } 56 | st->st_size = EXT2_I_SIZE(inode); 57 | st->st_blksize = EXT2_BLOCK_SIZE(e2fs->super); 58 | st->st_blocks = inode->i_blocks; 59 | st->st_atime = inode->i_atime; 60 | st->st_mtime = inode->i_mtime; 61 | st->st_ctime = inode->i_ctime; 62 | #if __FreeBSD__ == 10 63 | st->st_gen = inode->i_generation; 64 | #endif 65 | debugf("leave"); 66 | } 67 | -------------------------------------------------------------------------------- /fuse-ext2/do_killfilebyinode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | static int release_blocks_proc (ext2_filsys fs, blk_t *blocknr, int blockcnt, void *private) 24 | { 25 | blk_t block; 26 | 27 | debugf("enter"); 28 | 29 | block = *blocknr; 30 | ext2fs_block_alloc_stats(fs, block, -1); 31 | 32 | debugf("leave"); 33 | #ifdef CLEAN_UNUSED_BLOCKS 34 | *blocknr = 0; 35 | return BLOCK_CHANGED; 36 | #else 37 | return 0; 38 | #endif 39 | } 40 | 41 | int do_killfilebyinode (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode) 42 | { 43 | errcode_t rc; 44 | char scratchbuf[3*e2fs->blocksize]; 45 | 46 | debugf("enter"); 47 | 48 | inode->i_links_count = 0; 49 | inode->i_dtime = time(NULL); 50 | 51 | rc = ext2fs_write_inode(e2fs, ino, inode); 52 | if (rc) { 53 | debugf("ext2fs_write_inode(e2fs, ino, inode); failed"); 54 | return -EIO; 55 | } 56 | 57 | if (ext2fs_inode_has_valid_blocks(inode)) { 58 | debugf("start block delete for %d", ino); 59 | #ifdef CLEAN_UNUSED_BLOCKS 60 | ext2fs_block_iterate(e2fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE, scratchbuf, release_blocks_proc, NULL); 61 | #else 62 | ext2fs_block_iterate(e2fs, ino, 0, scratchbuf, release_blocks_proc, NULL); 63 | #endif 64 | } 65 | 66 | ext2fs_inode_alloc_stats2(e2fs, ino, -1, LINUX_S_ISDIR(inode->i_mode)); 67 | 68 | debugf("leave"); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /fuse-ext2/do_probe.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | #define VOLNAME_SIZE_MAX 16 24 | 25 | int do_probe (struct extfs_data *opts) 26 | { 27 | errcode_t rc; 28 | ext2_filsys e2fs; 29 | 30 | debugf_main("enter"); 31 | 32 | rc = ext2fs_open(opts->device, EXT2_FLAG_RW, 0, 0, unix_io_manager, &e2fs); 33 | if (rc) { 34 | debugf_main("Error while trying to open %s (rc=%d)", opts->device, rc); 35 | return -1; 36 | } 37 | #if 0 38 | rc = ext2fs_read_bitmaps(e2fs); 39 | if (rc) { 40 | debugf_main("Error while reading bitmaps (rc=%d)", rc); 41 | ext2fs_close(e2fs); 42 | return -2; 43 | } 44 | #endif 45 | if (e2fs->super != NULL) { 46 | opts->volname = (char *) malloc(sizeof(char) * (VOLNAME_SIZE_MAX + 1)); 47 | if (opts->volname != NULL) { 48 | memset(opts->volname, 0, sizeof(char) * (VOLNAME_SIZE_MAX + 1)); 49 | strncpy(opts->volname, e2fs->super->s_volume_name, VOLNAME_SIZE_MAX); 50 | opts->volname[VOLNAME_SIZE_MAX] = '\0'; 51 | } 52 | } 53 | ext2fs_close(e2fs); 54 | 55 | debugf_main("leave"); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /fuse-ext2/do_readinode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int do_readinode (ext2_filsys e2fs, const char *path, ext2_ino_t *ino, struct ext2_inode *inode) 24 | { 25 | errcode_t rc; 26 | rc = ext2fs_namei(e2fs, EXT2_ROOT_INO, EXT2_ROOT_INO, path, ino); 27 | if (rc) { 28 | debugf("ext2fs_namei(e2fs, EXT2_ROOT_INO, EXT2_ROOT_INO, %s, ino); failed", path); 29 | return -ENOENT; 30 | } 31 | rc = ext2fs_read_inode(e2fs, *ino, inode); 32 | if (rc) { 33 | debugf("ext2fs_read_inode(e2fs, *ino, inode); failed"); 34 | return -EIO; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /fuse-ext2/do_writeinode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int do_writeinode (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode) 24 | { 25 | int rt; 26 | errcode_t rc; 27 | if (inode->i_links_count < 1) { 28 | rt = do_killfilebyinode(e2fs, ino, inode); 29 | if (rt) { 30 | debugf("do_killfilebyinode(e2fs, ino, inode); failed"); 31 | return rt; 32 | } 33 | } else { 34 | rc = ext2fs_write_inode(e2fs, ino, inode); 35 | if (rc) { 36 | debugf("ext2fs_read_inode(e2fs, *ino, inode); failed"); 37 | return -EIO; 38 | } 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /fuse-ext2/fuse-ext2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | static const char *HOME = "http://github.com/alperakcan/fuse-ext2/"; 24 | 25 | #if __FreeBSD__ == 10 26 | static char def_opts[] = "allow_other,default_permissions,local,"; 27 | static char def_opts_rd[] = "noappledouble,"; 28 | #else 29 | static char def_opts[] = "allow_other,default_permissions,"; 30 | static char def_opts_rd[] = ""; 31 | #endif 32 | 33 | static const char *usage_msg = 34 | "\n" 35 | "%s %s %d - FUSE EXT2FS Driver\n" 36 | "\n" 37 | "Copyright (C) 2008-2015 Alper Akcan \n" 38 | "Copyright (C) 2009 Renzo Davoli \n" 39 | "\n" 40 | "Usage: %s [-o option[,...]]\n" 41 | "\n" 42 | "Options: ro, force, allow_other\n" 43 | " Please see details in the manual.\n" 44 | "\n" 45 | "Example: fuse-ext2 /dev/sda1 /mnt/sda1\n" 46 | "\n" 47 | "%s\n" 48 | "\n"; 49 | 50 | static int strappend (char **dest, const char *append) 51 | { 52 | char *p; 53 | size_t size; 54 | 55 | if (!dest) { 56 | return -1; 57 | } 58 | if (!append) { 59 | return 0; 60 | } 61 | 62 | size = strlen(append) + 1; 63 | if (*dest) { 64 | size += strlen(*dest); 65 | } 66 | 67 | p = realloc(*dest, size); 68 | if (!p) { 69 | debugf_main("Memory realloction failed"); 70 | return -1; 71 | } 72 | 73 | if (*dest) { 74 | strcat(p, append); 75 | } else { 76 | strcpy(p, append); 77 | } 78 | *dest = p; 79 | 80 | return 0; 81 | } 82 | 83 | static void usage (void) 84 | { 85 | printf(usage_msg, PACKAGE, VERSION, fuse_version(), PACKAGE, HOME); 86 | } 87 | 88 | static int parse_options (int argc, char *argv[], struct extfs_data *opts) 89 | { 90 | int c; 91 | 92 | static const char *sopt = "o:hv"; 93 | static const struct option lopt[] = { 94 | { "options", required_argument, NULL, 'o' }, 95 | { "help", no_argument, NULL, 'h' }, 96 | { "verbose", no_argument, NULL, 'v' }, 97 | { NULL, 0, NULL, 0 } 98 | }; 99 | 100 | #if 0 101 | printf("arguments;\n"); 102 | for (c = 0; c < argc; c++) { 103 | printf("%d: %s\n", c, argv[c]); 104 | } 105 | printf("done\n"); 106 | #endif 107 | 108 | opterr = 0; /* We'll handle the errors, thank you. */ 109 | 110 | while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { 111 | switch (c) { 112 | case 'o': 113 | if (opts->options) 114 | if (strappend(&opts->options, ",")) 115 | return -1; 116 | if (strappend(&opts->options, optarg)) 117 | return -1; 118 | break; 119 | case 'h': 120 | usage(); 121 | exit(9); 122 | case 'v': 123 | /* 124 | * We must handle the 'verbose' option even if 125 | * we don't use it because mount(8) passes it. 126 | */ 127 | opts->debug = 1; 128 | break; 129 | default: 130 | debugf_main("Unknown option '%s'", argv[optind - 1]); 131 | return -1; 132 | } 133 | } 134 | 135 | if (optind < argc) { 136 | optarg=argv[optind++]; 137 | if (optarg[0] != '/') { 138 | char fulldevice[PATH_MAX+1]; 139 | if (!realpath(optarg, fulldevice)) { 140 | debugf_main("Cannot mount %s", optarg); 141 | free(opts->device); 142 | opts->device = NULL; 143 | return -1; 144 | } else 145 | opts->device = strdup(fulldevice); 146 | } else 147 | opts->device = strdup(optarg); 148 | } 149 | 150 | if (optind < argc) { 151 | opts->mnt_point = argv[optind++]; 152 | } 153 | 154 | if (optind < argc) { 155 | debugf_main("You must specify exactly one device and exactly one mount point"); 156 | return -1; 157 | } 158 | 159 | if (!opts->device) { 160 | debugf_main("No device is specified"); 161 | return -1; 162 | } 163 | if (!opts->mnt_point) { 164 | debugf_main("No mountpoint is specified"); 165 | return -1; 166 | } 167 | 168 | return 0; 169 | } 170 | 171 | static char * parse_mount_options (const char *orig_opts, struct extfs_data *opts) 172 | { 173 | char *options, *s, *opt, *val, *ret; 174 | 175 | ret = malloc(strlen(def_opts) + strlen(def_opts_rd) + strlen(orig_opts) + 256 + PATH_MAX); 176 | if (!ret) { 177 | return NULL; 178 | } 179 | 180 | *ret = 0; 181 | options = strdup(orig_opts); 182 | if (!options) { 183 | debugf_main("strdup failed"); 184 | return NULL; 185 | } 186 | 187 | s = options; 188 | while (s && *s && (val = strsep(&s, ","))) { 189 | opt = strsep(&val, "="); 190 | if (!strcmp(opt, "ro")) { /* Read-only mount. */ 191 | if (val) { 192 | debugf_main("'ro' option should not have value"); 193 | goto err_exit; 194 | } 195 | opts->readonly = 1; 196 | strcat(ret, "ro,"); 197 | } else if (!strcmp(opt, "rw")) { /* Read-write mount */ 198 | if (val) { 199 | debugf_main("'rw' option should not have value"); 200 | goto err_exit; 201 | } 202 | opts->readonly = 0; 203 | strcat(ret, "rw,"); 204 | } else if (!strcmp(opt, "rw+")) { /* Read-write mount */ 205 | if (val) { 206 | debugf_main("'rw+' option should not have value"); 207 | goto err_exit; 208 | } 209 | opts->readonly = 0; 210 | opts->force = 1; 211 | strcat(ret, "rw,"); 212 | } else if (!strcmp(opt, "debug")) { /* enable debug */ 213 | if (val) { 214 | debugf_main("'debug' option should not have value"); 215 | goto err_exit; 216 | } 217 | opts->debug = 1; 218 | strcat(ret, "debug,"); 219 | } else if (!strcmp(opt, "silent")) { /* keep silent */ 220 | if (val) { 221 | debugf_main("'silent' option should not have value"); 222 | goto err_exit; 223 | } 224 | opts->silent = 1; 225 | } else if (!strcmp(opt, "force")) { /* enable read/write */ 226 | if (val) { 227 | debugf_main("'force option should no have value"); 228 | goto err_exit; 229 | } 230 | opts->force = 1; 231 | #if __FreeBSD__ == 10 232 | strcat(ret, "force,"); 233 | #endif 234 | } else { /* Probably FUSE option. */ 235 | strcat(ret, opt); 236 | if (val) { 237 | strcat(ret, "="); 238 | strcat(ret, val); 239 | } 240 | strcat(ret, ","); 241 | } 242 | } 243 | 244 | if (opts->readonly == 0 && opts->force == 0) { 245 | fprintf(stderr, "Mounting %s Read-Only.\nUse \'force\' or \'rw+\' options to enable Read-Write mode\n",opts->device); 246 | opts->readonly = 1; 247 | } 248 | 249 | strcat(ret, def_opts); 250 | if (opts->readonly == 1) { 251 | strcat(ret, def_opts_rd); 252 | strcat(ret, "ro,"); 253 | } 254 | strcat(ret, "fsname="); 255 | strcat(ret, opts->device); 256 | #if __FreeBSD__ == 10 257 | strcat(ret, ",fstypename="); 258 | strcat(ret, "ext2"); 259 | strcat(ret, ",volname="); 260 | if (opts->volname == NULL || opts->volname[0] == '\0') { 261 | s = strrchr(opts->device, '/'); 262 | if (s != NULL) { 263 | strcat(ret, s + 1); 264 | } else { 265 | strcat(ret, opts->device); 266 | } 267 | } else { 268 | strcat(ret, opts->volname); 269 | } 270 | #endif 271 | exit: 272 | free(options); 273 | return ret; 274 | err_exit: 275 | free(ret); 276 | ret = NULL; 277 | goto exit; 278 | } 279 | 280 | static const struct fuse_operations ext2fs_ops = { 281 | .getattr = op_getattr, 282 | .readlink = op_readlink, 283 | .mknod = op_mknod, 284 | .mkdir = op_mkdir, 285 | .unlink = op_unlink, 286 | .rmdir = op_rmdir, 287 | .symlink = op_symlink, 288 | .rename = op_rename, 289 | .link = op_link, 290 | .chmod = op_chmod, 291 | .chown = op_chown, 292 | .truncate = op_truncate, 293 | .open = op_open, 294 | .read = op_read, 295 | .write = op_write, 296 | .statfs = op_statfs, 297 | .flush = op_flush, 298 | .release = op_release, 299 | .fsync = op_fsync, 300 | .setxattr = NULL, 301 | .getxattr = op_getxattr, 302 | .listxattr = NULL, 303 | .removexattr = NULL, 304 | .opendir = op_open, 305 | .readdir = op_readdir, 306 | .releasedir = op_release, 307 | .fsyncdir = op_fsync, 308 | .init = op_init, 309 | .destroy = op_destroy, 310 | .access = op_access, 311 | .create = op_create, 312 | .ftruncate = op_ftruncate, 313 | .fgetattr = op_fgetattr, 314 | .lock = NULL, 315 | .utimens = op_utimens, 316 | .bmap = NULL, 317 | #if ( (FUSE_VERSION) == 29 ) 318 | .flag_utime_omit_ok = 1, 319 | #endif 320 | }; 321 | 322 | int main (int argc, char *argv[]) 323 | { 324 | int err = 0; 325 | struct stat sbuf; 326 | char *parsed_options = NULL; 327 | struct fuse_args fargs = FUSE_ARGS_INIT(0, NULL); 328 | struct extfs_data opts; 329 | 330 | debugf_main("version:'%s', fuse_version:'%d / %d / %d'", VERSION, FUSE_USE_VERSION, FUSE_VERSION, fuse_version()); 331 | 332 | memset(&opts, 0, sizeof(opts)); 333 | 334 | if (parse_options(argc, argv, &opts)) { 335 | usage(); 336 | return -1; 337 | } 338 | 339 | if (stat(opts.device, &sbuf)) { 340 | debugf_main("Failed to access '%s'", opts.device); 341 | err = -3; 342 | goto err_out; 343 | } 344 | 345 | if (do_probe(&opts) != 0) { 346 | debugf_main("Probe failed"); 347 | err = -4; 348 | goto err_out; 349 | } 350 | 351 | parsed_options = parse_mount_options(opts.options ? opts.options : "", &opts); 352 | if (!parsed_options) { 353 | err = -2; 354 | goto err_out; 355 | } 356 | 357 | debugf_main("opts.device: %s", opts.device); 358 | debugf_main("opts.mnt_point: %s", opts.mnt_point); 359 | debugf_main("opts.volname: %s", (opts.volname != NULL) ? opts.volname : ""); 360 | debugf_main("opts.options: %s", opts.options); 361 | debugf_main("parsed_options: %s", parsed_options); 362 | 363 | if (fuse_opt_add_arg(&fargs, PACKAGE) == -1 || 364 | fuse_opt_add_arg(&fargs, "-s") == -1 || 365 | fuse_opt_add_arg(&fargs, "-o") == -1 || 366 | fuse_opt_add_arg(&fargs, parsed_options) == -1 || 367 | fuse_opt_add_arg(&fargs, opts.mnt_point) == -1) { 368 | debugf_main("Failed to set FUSE options"); 369 | fuse_opt_free_args(&fargs); 370 | err = -5; 371 | goto err_out; 372 | } 373 | 374 | if (opts.readonly == 0) { 375 | debugf_main("mounting read-write"); 376 | } else { 377 | debugf_main("mounting read-only"); 378 | } 379 | 380 | err = fuse_main(fargs.argc, fargs.argv, &ext2fs_ops, &opts); 381 | 382 | err_out: 383 | fuse_opt_free_args(&fargs); 384 | free(parsed_options); 385 | free(opts.options); 386 | free(opts.device); 387 | free(opts.volname); 388 | return err; 389 | } 390 | -------------------------------------------------------------------------------- /fuse-ext2/fuse-ext2.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program (in the main directory of the fuse-ext2 16 | * distribution in the file COPYING); if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #ifndef FUSEEXT2_H_ 21 | #define FUSEEXT2_H_ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #ifdef MAJOR_IN_SYSMACROS 34 | # include 35 | #endif 36 | 37 | #include 38 | #include 39 | 40 | #if !defined(FUSE_VERSION) || (FUSE_VERSION < 26) 41 | #error "***********************************************************" 42 | #error "* *" 43 | #error "* Compilation requires at least FUSE version 2.6.0! *" 44 | #error "* *" 45 | #error "***********************************************************" 46 | #endif 47 | 48 | /* extra definitions not yet included in ext2fs.h */ 49 | #define EXT2_FILE_SHARED_INODE 0x8000 50 | errcode_t ext2fs_file_close2(ext2_file_t file, void (*close_callback) (struct ext2_inode *inode, int flags)); 51 | 52 | #ifndef PATH_MAX 53 | #define PATH_MAX 4096 54 | #endif 55 | 56 | #define EXT2FS_FILE(efile) ((void *) (unsigned long) (efile)) 57 | /* max timeout to flush bitmaps, to reduce inconsistencies */ 58 | #define FLUSH_BITMAPS_TIMEOUT 10 59 | 60 | struct extfs_data { 61 | unsigned char debug; 62 | unsigned char silent; 63 | unsigned char force; 64 | unsigned char readonly; 65 | time_t last_flush; 66 | char *mnt_point; 67 | char *options; 68 | char *device; 69 | char *volname; 70 | ext2_filsys e2fs; 71 | }; 72 | 73 | static inline ext2_filsys current_ext2fs(void) 74 | { 75 | struct fuse_context *mycontext=fuse_get_context(); 76 | struct extfs_data *e2data=mycontext->private_data; 77 | time_t now=time(NULL); 78 | if ((now - e2data->last_flush) > FLUSH_BITMAPS_TIMEOUT) { 79 | ext2fs_write_bitmaps(e2data->e2fs); 80 | e2data->last_flush=now; 81 | } 82 | return (ext2_filsys) e2data->e2fs; 83 | } 84 | 85 | static inline uid_t ext2_read_uid(struct ext2_inode *inode) 86 | { 87 | return ((uid_t)inode->osd2.linux2.l_i_uid_high << 16) | inode->i_uid; 88 | } 89 | 90 | static inline void ext2_write_uid(struct ext2_inode *inode, uid_t uid) 91 | { 92 | inode->i_uid = uid & 0xffff; 93 | inode->osd2.linux2.l_i_uid_high = (uid >> 16) & 0xffff; 94 | } 95 | 96 | static inline gid_t ext2_read_gid(struct ext2_inode *inode) 97 | { 98 | return ((gid_t)inode->osd2.linux2.l_i_gid_high << 16) | inode->i_gid; 99 | } 100 | 101 | static inline void ext2_write_gid(struct ext2_inode *inode, gid_t gid) 102 | { 103 | inode->i_gid = gid & 0xffff; 104 | inode->osd2.linux2.l_i_gid_high = (gid >> 16) & 0xffff; 105 | } 106 | 107 | #if ENABLE_DEBUG 108 | 109 | static inline void debug_printf (const char *function, char *file, int line, const char *fmt, ...) 110 | { 111 | va_list args; 112 | struct fuse_context *mycontext=fuse_get_context(); 113 | struct extfs_data *e2data=mycontext->private_data; 114 | if (e2data && (e2data->debug == 0 || e2data->silent == 1)) { 115 | return; 116 | } 117 | printf("%s: ", PACKAGE); 118 | va_start(args, fmt); 119 | vprintf(fmt, args); 120 | va_end(args); 121 | printf(" [%s (%s:%d)]\n", function, file, line); 122 | } 123 | 124 | #define debugf(a...) { \ 125 | debug_printf(__FUNCTION__, __FILE__, __LINE__, a); \ 126 | } 127 | 128 | static inline void debug_main_printf (const char *function, char *file, int line, const char *fmt, ...) 129 | { 130 | va_list args; 131 | printf("%s: ", PACKAGE); 132 | va_start(args, fmt); 133 | vprintf(fmt, args); 134 | va_end(args); 135 | printf(" [%s (%s:%d)]\n", function, file, line); 136 | } 137 | 138 | #define debugf_main(a...) { \ 139 | debug_main_printf(__FUNCTION__, __FILE__, __LINE__, a); \ 140 | } 141 | 142 | #else /* ENABLE_DEBUG */ 143 | 144 | #define debugf(a...) do { } while(0) 145 | #define debugf_main(a...) do { } while(0) 146 | 147 | #endif /* ENABLE_DEBUG */ 148 | 149 | void * op_init (struct fuse_conn_info *conn); 150 | 151 | void op_destroy (void *userdata); 152 | 153 | /* helper functions */ 154 | 155 | int do_probe (struct extfs_data *opts); 156 | 157 | int do_label (void); 158 | 159 | int do_check (const char *path); 160 | 161 | int do_check_split(const char *path, char **dirname,char **basename); 162 | 163 | void free_split(char *dirname, char *basename); 164 | 165 | void do_fillstatbuf (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode, struct stat *st); 166 | 167 | int do_readinode (ext2_filsys e2fs, const char *path, ext2_ino_t *ino, struct ext2_inode *inode); 168 | 169 | int do_writeinode (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode); 170 | 171 | int do_killfilebyinode (ext2_filsys e2fs, ext2_ino_t ino, struct ext2_inode *inode); 172 | 173 | /* read support */ 174 | 175 | int op_access (const char *path, int mask); 176 | 177 | int op_fgetattr (const char *path, struct stat *stbuf, struct fuse_file_info *fi); 178 | 179 | int op_getattr (const char *path, struct stat *stbuf); 180 | 181 | int op_getxattr(const char *path, const char *name, char *value, size_t size); 182 | 183 | ext2_file_t do_open (ext2_filsys e2fs, const char *path, int flags); 184 | 185 | int op_open (const char *path, struct fuse_file_info *fi); 186 | 187 | int op_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi); 188 | 189 | int op_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi); 190 | 191 | int op_readlink (const char *path, char *buf, size_t size); 192 | 193 | int do_release (ext2_file_t efile); 194 | 195 | int op_release (const char *path, struct fuse_file_info *fi); 196 | 197 | int op_statfs(const char *path, struct statvfs *buf); 198 | 199 | /* write support */ 200 | 201 | int do_modetoext2lag (mode_t mode); 202 | 203 | int op_chmod (const char *path, mode_t mode); 204 | 205 | int op_chown (const char *path, uid_t uid, gid_t gid); 206 | 207 | int do_create (ext2_filsys e2fs, const char *path, mode_t mode, dev_t dev, const char *fastsymlink); 208 | 209 | int op_create (const char *path, mode_t mode, struct fuse_file_info *fi); 210 | 211 | int op_flush (const char *path, struct fuse_file_info *fi); 212 | 213 | int op_fsync (const char *path, int datasync, struct fuse_file_info *fi); 214 | 215 | int op_mkdir (const char *path, mode_t mode); 216 | 217 | int do_check_empty_dir(ext2_filsys e2fs, ext2_ino_t ino); 218 | 219 | int op_rmdir (const char *path); 220 | 221 | int op_unlink (const char *path); 222 | 223 | int op_utimens (const char *path, const struct timespec tv[2]); 224 | 225 | size_t do_write (ext2_file_t efile, const char *buf, size_t size, off_t offset); 226 | 227 | int op_write (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi); 228 | 229 | int op_mknod (const char *path, mode_t mode, dev_t dev); 230 | 231 | int op_symlink (const char *sourcename, const char *destname); 232 | 233 | int op_truncate(const char *path, off_t length); 234 | 235 | int op_ftruncate(const char *path, off_t length, struct fuse_file_info *fi); 236 | 237 | int op_link (const char *source, const char *dest); 238 | 239 | int op_rename (const char *source, const char *dest); 240 | 241 | #endif /* FUSEEXT2_H_ */ 242 | -------------------------------------------------------------------------------- /fuse-ext2/fuse-ext2.probe.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | static const char *HOME = "http://sourceforge.net/projects/fuse-ext2/"; 24 | 25 | static const char *usage_msg = 26 | "\n" 27 | "%s %s %d - Probe EXT2FS volume mountability\n" 28 | "\n" 29 | "Copyright (C) 2008-2015 Alper Akcan \n" 30 | "\n" 31 | "Usage: %s <--readonly|--readwrite> \n" 32 | "\n" 33 | "Example: fuse-ext2.probe --readwrite /dev/sda1\n" 34 | "\n" 35 | "%s\n" 36 | "\n"; 37 | 38 | static void usage (void) 39 | { 40 | printf(usage_msg, PACKAGE, VERSION, fuse_version(), PACKAGE, HOME); 41 | } 42 | 43 | static int parse_options (int argc, char *argv[], struct extfs_data *opts) 44 | { 45 | int c; 46 | 47 | static const char *sopt = "-rwd"; 48 | static const struct option lopt[] = { 49 | { "readonly", no_argument, NULL, 'r' }, 50 | { "readwrite", no_argument, NULL, 'w' }, 51 | { "debug", no_argument, NULL, 'd' }, 52 | { NULL, 0, NULL, 0 } 53 | }; 54 | 55 | opterr = 0; /* We'll handle the errors, thank you. */ 56 | 57 | while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { 58 | switch (c) { 59 | case 1: /* A non-option argument */ 60 | if (!opts->device) { 61 | opts->device = malloc(PATH_MAX + 1); 62 | if (!opts->device) 63 | return -1; 64 | 65 | /* We don't want relative path in /etc/mtab. */ 66 | if (optarg[0] != '/') { 67 | if (!realpath(optarg, opts->device)) { 68 | debugf_main("Cannot mount %s", optarg); 69 | free(opts->device); 70 | opts->device = NULL; 71 | return -1; 72 | } 73 | } else 74 | strcpy(opts->device, optarg); 75 | } else { 76 | debugf_main("You must specify exactly one device"); 77 | return -1; 78 | } 79 | break; 80 | case 'r': 81 | opts->readonly = 1; 82 | break; 83 | case 'w': 84 | opts->readonly = 0; 85 | break; 86 | case 'd': 87 | opts->debug = 1; 88 | break; 89 | default: 90 | debugf_main("Unknown option '%s'", argv[optind - 1]); 91 | return -1; 92 | } 93 | } 94 | 95 | if (!opts->device) { 96 | debugf_main("No device is specified"); 97 | return -1; 98 | } 99 | 100 | return 0; 101 | } 102 | 103 | int main (int argc, char *argv[]) 104 | { 105 | int err = 0; 106 | struct stat sbuf; 107 | struct extfs_data opts; 108 | 109 | memset(&opts, 0, sizeof(opts)); 110 | 111 | if (parse_options(argc, argv, &opts)) { 112 | usage(); 113 | return -1; 114 | } 115 | 116 | if (stat(opts.device, &sbuf)) { 117 | debugf_main("Failed to access '%s'", opts.device); 118 | err = -3; 119 | goto err_out; 120 | } 121 | 122 | debugf_main("opts.device: %s", opts.device); 123 | 124 | if (do_probe(&opts) != 0) { 125 | debugf_main("Probe failed"); 126 | err = -4; 127 | goto err_out; 128 | } 129 | 130 | err_out: 131 | free(opts.device); 132 | free(opts.volname); 133 | free(opts.options); 134 | return err; 135 | } 136 | -------------------------------------------------------------------------------- /fuse-ext2/fuse-ext2.uninstall.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program (in the main directory of the fuse-ext2 16 | * distribution in the file COPYING); if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #define debugf(a...) { \ 31 | printf("fuse-ext2.uninstall: "); \ 32 | printf(a); \ 33 | printf(" (%s) [%s (%s:%d)]\n", strerror(errno), __FUNCTION__, __FILE__, __LINE__); \ 34 | } 35 | 36 | static int verbose = 0; 37 | static int uninstall = 0; 38 | 39 | static char *files[] = { 40 | "/Library/Receipts/fuse-ext2.pkg", 41 | "/Library/Filesystems/fuse-ext2.fs", 42 | "/System/Library/Filesystems/fuse-ext2.fs", 43 | "/Library/PreferencePanes/fuse-ext2.prefPane", 44 | "/System/Library/PreferencePanes/fuse-ext2.prefPane", 45 | "/usr/local/bin/fuse-ext2", 46 | "/usr/local/bin/fuse-ext2.wait", 47 | "/usr/local/bin/fuse-ext2.probe", 48 | "/usr/local/bin/fuse-ext2.mke2fs", 49 | "/usr/local/bin/fuse-ext2.e2label", 50 | "/usr/local/bin/fuse-ext2.install", 51 | "/usr/local/bin/fuse-ext2.uninstall", 52 | "/usr/local/lib/pkgconfig/fuse-ext2.pc", 53 | "/usr/local/share/man/man1/fuse-ext2.1", 54 | NULL, 55 | }; 56 | 57 | static int rm_file (const char *path) 58 | { 59 | printf("removing file '%s'\n", path); 60 | if (verbose == 0 && unlink(path) != 0) { 61 | debugf("unlink failed for '%s'", path); 62 | } 63 | return 0; 64 | } 65 | 66 | static int rm_directory (const char *path) 67 | { 68 | DIR *dp; 69 | char *p; 70 | struct stat stbuf; 71 | struct dirent *current; 72 | dp = opendir(path); 73 | if (dp == NULL) { 74 | debugf("opendir() failed for '%s'", path); 75 | if (errno == ENOENT) { 76 | return 0; 77 | } 78 | return -1; 79 | } 80 | while ((current = readdir(dp)) != NULL) { 81 | if (strcmp(current->d_name, ".") == 0 || 82 | strcmp(current->d_name, "..") == 0) { 83 | continue; 84 | } 85 | p = (char *) malloc(sizeof(char) * (strlen(path) + 1 + strlen(current->d_name) + 1)); 86 | if (p == NULL) { 87 | debugf("malloc failed for '%s/%s'", path, current->d_name); 88 | continue; 89 | } 90 | sprintf(p, "%s/%s", path, current->d_name); 91 | if (lstat(p, &stbuf) != 0) { 92 | debugf("lstat failed for '%s'", p); 93 | free(p); 94 | continue; 95 | } 96 | if (S_ISDIR(stbuf.st_mode)) { 97 | if (rm_directory(p) != 0) { 98 | debugf("rm_directory() failed for '%s'", p); 99 | } 100 | } else { 101 | if (rm_file(p) != 0) { 102 | debugf("rm_file() failed for '%s'", p); 103 | } 104 | } 105 | free(p); 106 | } 107 | closedir(dp); 108 | printf("removing directory '%s'\n", path); 109 | if (verbose == 0 && rmdir(path) != 0) { 110 | debugf("rmdir() failed for '%s'", path); 111 | } 112 | return 0; 113 | } 114 | 115 | static int rm_path (const char *path) 116 | { 117 | struct stat stbuf; 118 | if (lstat(path, &stbuf) != 0) { 119 | debugf("lstat failed for '%s'", path); 120 | return -1; 121 | } 122 | if (S_ISDIR(stbuf.st_mode)) { 123 | return rm_directory(path); 124 | } else { 125 | return rm_file(path); 126 | } 127 | return -1; 128 | } 129 | 130 | static void print_help (const char *pname) 131 | { 132 | printf("%s usage;\n", pname); 133 | printf(" uninstall / u : do uninstall [ just for safety ]\n"); 134 | printf(" verbose / v : just print, do not remove\n"); 135 | printf(" help / h : this text\n"); 136 | printf(" example;\n"); 137 | printf(" %s -u\n", pname); 138 | printf(" %s -u -v\n", pname); 139 | } 140 | 141 | int main (int argc, char *argv[]) 142 | { 143 | int c; 144 | static const char *sopt = "uvh"; 145 | static const struct option lopt[] = { 146 | { "uninstall", no_argument, NULL, 'u'}, 147 | { "verbose", no_argument, NULL, 'v' }, 148 | { "help", no_argument, NULL, 'h' }, 149 | { NULL, 0, NULL, 0 } 150 | }; 151 | 152 | char **f; 153 | 154 | while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { 155 | switch (c) { 156 | case 'u': 157 | uninstall = 1; 158 | break; 159 | case 'v': 160 | verbose = 1; 161 | break; 162 | case 'h': 163 | print_help(argv[0]); 164 | return 0; 165 | } 166 | } 167 | 168 | if (uninstall == 0) { 169 | print_help(argv[0]); 170 | return -1; 171 | } 172 | 173 | printf("uninstalling fuse-ext2\n"); 174 | for (f = files; *f != NULL; f++) { 175 | if (rm_path(*f) != 0) { 176 | debugf("rm_path() for '%s' failed", *f); 177 | } 178 | } 179 | printf("done\n"); 180 | return 0; 181 | } 182 | -------------------------------------------------------------------------------- /fuse-ext2/fuse-ext2.wait.m: -------------------------------------------------------------------------------- 1 | /*- 2 | * fuse_wait - Light wrapper around a FUSE mount program that waits 3 | * for the "mounted" notification before exiting. 4 | * 5 | * Copyright (C) 2007 Erik Larsson 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA 21 | */ 22 | 23 | /* 24 | * fuse_wait 25 | * Written as a replacement to shadowofged's little utility. 26 | * This tool executes a specified mount program with all of its 27 | * arguments. The path to the mount program and all its arguments 28 | * start at the third argument. The first argument is the mount 29 | * point to check for mount notification, and the second argument 30 | * is the amount of seconds to wait until timeout. 31 | * Primarily used for mounting ntfs-3g filesystems on Mac OS X. 32 | * 33 | * Updated 2007-10-07: 34 | * I didn't read the man page for waitpid correctly. fuse_wait 35 | * thus returned incorrect exit values, but it's fixed now. 36 | */ 37 | 38 | #include 39 | #include 40 | #include // for realpath 41 | #include 42 | 43 | #define FUSE_LISTEN_OBJECT "com.google.filesystems.fusefs.unotifications" 44 | #define FUSE_MOUNT_NOTIFICATION_NAME "com.google.filesystems.fusefs.unotifications.mounted" 45 | #define FUSE_MOUNT_PATH_KEY "kFUSEMountPath" 46 | #define DEBUGMODE FALSE 47 | #if DEBUGMODE 48 | #define DEBUG(...) do { fprintf(debugFile, __VA_ARGS__); fflush(debugFile); } while(0) 49 | static FILE *debugFile = stderr; 50 | #else 51 | #define DEBUG(...) 52 | #endif 53 | 54 | #define MIN(X, Y) X < Y ? X : Y 55 | 56 | static CFStringRef mountPath = NULL; 57 | 58 | /* There seems to be a bug with MacFUSE such that the CFString that 59 | * it returns for kFUSEMountPath in the dictionary accompanying the 60 | * com.google.filesystems.fusefs.unotifications.mounted notification 61 | * is represented as UTF-8 within the internal representation. 62 | * Probably UTF-8 encoded text represented as UTF-16 values. This 63 | * function transforms it to a true null terminated UTF-8 string. 64 | * This function assumes that the target buffer out is at least 65 | * CFStringGetLength(in) bytes long. */ 66 | static void GetCorruptedMacFUSEStringAsUTF8(CFStringRef in, char* out, int outsize) { 67 | int inLength = CFStringGetLength(in); 68 | int bytesToWrite = MIN(inLength, outsize-1); 69 | int i; 70 | for(i = 0; i < bytesToWrite; ++i) 71 | out[i] = (char)CFStringGetCharacterAtIndex(in, i); 72 | out[i] = '\0'; 73 | } 74 | 75 | /* Debug code for printing entries in the CFDictionary 'userInfo'. */ 76 | static void PrintDictEntry(const void *key, const void *value, void *context) { 77 | char buffer[512]; 78 | CFStringGetCString(key, buffer, 512, kCFStringEncodingUTF8); 79 | DEBUG(" Key: \"%s\"", buffer); 80 | GetCorruptedMacFUSEStringAsUTF8(value, buffer, 512); 81 | DEBUG(", Value: \"%s\"\n", buffer); 82 | /* FILE *dbgoutput = fopen("valuedump-utf32be.txt", "w"); */ 83 | /* memset(buffer, 0, 512); */ 84 | /* CFStringGetCString(value, buffer, 512, kCFStringEncodingUTF32BE); */ 85 | /* fwrite(buffer, 512, 1, dbgoutput); */ 86 | /* fclose(dbgoutput); */ 87 | } 88 | 89 | /* Callback function which will recieve the 'mounted' notification 90 | * from FUSE. It is full with debug code... but I'll let it stay 91 | * that way. */ 92 | static void NotificationCallback(CFNotificationCenterRef center, 93 | void *observer, 94 | CFStringRef name, 95 | const void *object, 96 | CFDictionaryRef userInfo) { 97 | if(DEBUGMODE) { 98 | char buffer[512]; 99 | DEBUG("Received notification:\n"); 100 | if(CFStringGetCString(name, buffer, 512, kCFStringEncodingUTF8) == true) 101 | DEBUG(" Name: %s\n", buffer); 102 | else 103 | DEBUG(" \n"); 104 | } 105 | if(userInfo != NULL) { // It's only null when testing 106 | DEBUG(" userInfo:\n"); 107 | if(DEBUGMODE) CFDictionaryApplyFunction(userInfo, PrintDictEntry, NULL); 108 | 109 | const void *value = NULL; 110 | DEBUG("CFDictionaryGetValueIfPresent(%X, \"%s\", %X\n", 111 | (int)userInfo, FUSE_MOUNT_PATH_KEY, (int)&value); 112 | 113 | if(CFDictionaryGetValueIfPresent(userInfo, CFSTR(FUSE_MOUNT_PATH_KEY), &value) == true) { 114 | DEBUG("CFGetTypeID(%X) == %X ?\n", (int)value, (int)CFStringGetTypeID()); 115 | if(CFGetTypeID((CFStringRef)value) == CFStringGetTypeID()) { 116 | DEBUG("mountPath=%X\n", (int)mountPath); 117 | if(mountPath != NULL) 118 | CFRelease(mountPath); // No memory leaks please. 119 | DEBUG("assigning mountpath the value %X\n", (int)value); 120 | 121 | mountPath = (CFStringRef)value; 122 | CFRetain(mountPath); 123 | 124 | DEBUG("done with assigning.\n"); 125 | } 126 | } 127 | } 128 | } 129 | 130 | /* Prints a help text to a stream. */ 131 | static void PrintUsage(FILE *stream) { 132 | /* 80 chars <-------------------------------------------------------------------------------->*/ 133 | fprintf(stream, "usage: fuse_wait []\n"); 134 | fprintf(stream, " mountpoint - where you wish to mount the MacFUSE file system\n"); 135 | fprintf(stream, " timeout - time (in seconds) to wait for the mount operation to\n"); 136 | fprintf(stream, " complete (may be a floating point value)\n"); 137 | fprintf(stream, " mount_command - a path to the executable file containing the fuse program\n"); 138 | fprintf(stream, " used to mount the file system\n"); 139 | fprintf(stream, " args - the arguments that you would normally pass to \n"); 140 | fprintf(stream, " (note that this includes the mount point)\n"); 141 | } 142 | 143 | int main(int argc, char** argv) { 144 | if(argc < 4) { 145 | PrintUsage(stdout); 146 | return 0; 147 | } 148 | 149 | /* */ 150 | 151 | /* Parse argument: mountpoint (CFString) */ 152 | /*CFStringRef mountpoint = CFStringCreateWithCString(kCFAllocatorDefault, 153 | argv[1], kCFStringEncodingUTF8); */ 154 | /* Parse argument: mountpointRaw (char*) */ 155 | char *mountpointRaw = argv[1]; 156 | 157 | /* Parse argument: timeout (double) */ 158 | double timeout; 159 | { 160 | CFStringRef timeoutString = CFStringCreateWithCString(kCFAllocatorDefault, 161 | argv[2], kCFStringEncodingUTF8); 162 | timeout = CFStringGetDoubleValue(timeoutString); 163 | CFRelease(timeoutString); 164 | if(timeout == 0.0) { 165 | fprintf(stdout, "Invalid argument: timeout (\"%s\"", argv[2]); 166 | return -1; 167 | } 168 | } 169 | 170 | /* Parse argument: mount_command */ 171 | const char *mount_command = argv[3]; 172 | 173 | /* */ 174 | 175 | CFNotificationCenterRef centerRef; 176 | CFStringRef notificationObjectName = CFSTR(FUSE_LISTEN_OBJECT); 177 | CFStringRef notificationName = CFSTR(FUSE_MOUNT_NOTIFICATION_NAME); 178 | CFRunLoopRef crl; 179 | 180 | if(DEBUGMODE) { 181 | DEBUG("Testing NotificationCallback...\n"); 182 | NotificationCallback(NULL, NULL, notificationObjectName, NULL, NULL); 183 | DEBUG("Test completed. Adding observer...\n"); 184 | } 185 | 186 | centerRef = CFNotificationCenterGetDistributedCenter(); 187 | crl = CFRunLoopGetCurrent(); 188 | 189 | /* Think. Will the child process also be an observer? I don't think so... */ 190 | CFNotificationCenterAddObserver(centerRef, NULL, NotificationCallback, notificationName, 191 | notificationObjectName, CFNotificationSuspensionBehaviorDrop); 192 | 193 | 194 | int forkRetval = fork(); 195 | if(forkRetval == -1) { 196 | fprintf(stderr, "Could not fork!\n"); 197 | return -1; 198 | } 199 | else if(forkRetval != 0) { 200 | // Parent process 201 | int childProcessPID = forkRetval; 202 | 203 | int waitpid_status = 0; 204 | DEBUG("Waiting for PID %d...\n", childProcessPID); 205 | int waitpidres = waitpid(childProcessPID, &waitpid_status, 0); 206 | if(waitpidres == childProcessPID) { 207 | if(!WIFEXITED(waitpid_status)) { 208 | DEBUG("Child process did not exit cleanly! Returning -1."); 209 | return -1; 210 | } 211 | 212 | int retval = WEXITSTATUS(waitpid_status); 213 | DEBUG("PID %d returned with exit code: %d Exiting fuse_wait with this exit code...\n", childProcessPID, retval); 214 | if(retval != 0) { 215 | DEBUG("Exit value indicates an error while executing mount command. Returning without\n"); 216 | DEBUG("waiting for notification.\n"); 217 | DEBUG("Returning retval: %d\n", retval); 218 | return retval; 219 | } 220 | } 221 | else { 222 | DEBUG("Abnormal termination of process %d. :( waitpid returned: %d\n", childProcessPID, waitpidres); 223 | return -1; 224 | } 225 | 226 | DEBUG("Running run loop a long time...\n"); 227 | CFStringRef mountPathSnapshot = NULL; 228 | while(mountPathSnapshot == NULL) { 229 | int crlrimRetval = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, true); 230 | DEBUG("Exited from run loop. Let's find out why... crlrimRetval: %d (handled: %d)\n", crlrimRetval, kCFRunLoopRunHandledSource); 231 | mountPathSnapshot = mountPath; // Might have been modified during run loop. 232 | if(crlrimRetval != kCFRunLoopRunHandledSource) { 233 | fprintf(stderr, "Did not receive a signal within %f seconds. Exiting...\n", timeout); 234 | break; 235 | } 236 | else if(mountPathSnapshot != NULL) { 237 | DEBUG("mountPathSnapshot: %X\n", (int)mountPathSnapshot); 238 | 239 | int mountPathUTF8Length = CFStringGetLength(mountPath) + 1; // null terminator 240 | char *mountPathUTF8 = malloc(mountPathUTF8Length); 241 | memset(mountPathUTF8, 0, mountPathUTF8Length); 242 | GetCorruptedMacFUSEStringAsUTF8(mountPath, mountPathUTF8, mountPathUTF8Length); 243 | 244 | char *canonicalMountPath = malloc(PATH_MAX); 245 | char *canonicalMountpoint = malloc(PATH_MAX); 246 | memset(canonicalMountPath, 0, PATH_MAX); 247 | memset(canonicalMountpoint, 0, PATH_MAX); 248 | 249 | realpath(mountPathUTF8, canonicalMountPath); 250 | realpath(mountpointRaw, canonicalMountpoint); 251 | 252 | int cmpres = strncmp(canonicalMountPath, canonicalMountpoint, PATH_MAX); 253 | 254 | if(cmpres != 0) { 255 | if(DEBUGMODE) { 256 | DEBUG("Strings NOT equal. cmpres=%d\n", cmpres); 257 | DEBUG("mountPath (UTF-8): \"%s\"\n", canonicalMountPath); 258 | DEBUG("mountpoint (UTF-8): \"%s\"\n", canonicalMountpoint); 259 | } 260 | mountPathSnapshot = NULL; 261 | } 262 | else 263 | DEBUG("Mounter has signaled! Great success!\n"); 264 | 265 | free(mountPathUTF8); 266 | free(canonicalMountPath); 267 | free(canonicalMountpoint); 268 | } 269 | //CFRunLoopRun(); 270 | } 271 | DEBUG("Run loop done.\n"); 272 | if(mountPath != NULL) 273 | CFRelease(mountPath); 274 | 275 | return 0; // We have previously checked that the return value from the child process is 0. We can't get here if it isn't. 276 | } 277 | else { // forkRetval == 0 278 | // Child process 279 | const int childargc = argc-3; 280 | char *childargv[childargc+1]; 281 | childargv[childargc] = NULL; // Null terminated 282 | int i; 283 | for(i = 0; i < childargc; ++i) 284 | childargv[i] = argv[i+(argc-childargc)]; 285 | 286 | if(DEBUGMODE) { 287 | DEBUG("Contents of argv:\n"); 288 | for(i = 0; i < argc; ++i) 289 | DEBUG(" argv[%i]: \"%s\"\n", i, argv[i]); 290 | 291 | DEBUG("Contents of childargv:\n"); 292 | for(i = 0; i < childargc; ++i) 293 | DEBUG(" childargv[%i]: \"%s\"\n", i, childargv[i]); 294 | } 295 | 296 | execvp(mount_command, childargv); 297 | fprintf(stderr, "Could not execute %s!\n", argv[3]); 298 | return -1; 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /fuse-ext2/op_access.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | #include 23 | 24 | int op_access (const char *path, int mask) 25 | { 26 | int rt; 27 | ext2_filsys e2fs = current_ext2fs(); 28 | 29 | debugf("enter"); 30 | debugf("path = %s, mask = 0%o", path, mask); 31 | 32 | rt = do_check(path); 33 | if (rt != 0) { 34 | debugf("do_check(%s); failed", path); 35 | return rt; 36 | } 37 | 38 | if ((mask & W_OK) && !(e2fs->flags & EXT2_FLAG_RW)) { 39 | return -EACCES; 40 | } 41 | 42 | debugf("leave"); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /fuse-ext2/op_chmod.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_chmod (const char *path, mode_t mode) 24 | { 25 | int rt; 26 | int mask; 27 | time_t tm; 28 | ext2_ino_t ino; 29 | struct ext2_inode inode; 30 | ext2_filsys e2fs = current_ext2fs(); 31 | 32 | debugf("enter"); 33 | debugf("path = %s 0%o", path, mode); 34 | 35 | rt = do_check(path); 36 | if (rt != 0) { 37 | debugf("do_check(%s); failed", path); 38 | return rt; 39 | } 40 | 41 | rt = do_readinode(e2fs, path, &ino, &inode); 42 | if (rt) { 43 | debugf("do_readinode(%s, &ino, &vnode); failed", path); 44 | return rt; 45 | } 46 | 47 | tm = e2fs->now ? e2fs->now : time(NULL); 48 | mask = S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX; 49 | inode.i_mode = (inode.i_mode & ~mask) | (mode & mask); 50 | inode.i_ctime = tm; 51 | 52 | rt = do_writeinode(e2fs, ino, &inode); 53 | if (rt) { 54 | debugf("do_writeinode(e2fs, ino, &inode); failed"); 55 | return -EIO; 56 | } 57 | 58 | debugf("leave"); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /fuse-ext2/op_chown.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_chown (const char *path, uid_t uid, gid_t gid) 24 | { 25 | int rt; 26 | ext2_ino_t ino; 27 | struct ext2_inode inode; 28 | ext2_filsys e2fs = current_ext2fs(); 29 | 30 | debugf("enter"); 31 | debugf("path = %s", path); 32 | 33 | rt = do_check(path); 34 | if (rt != 0) { 35 | debugf("do_check(%s); failed", path); 36 | return rt; 37 | } 38 | 39 | rt = do_readinode(e2fs, path, &ino, &inode); 40 | if (rt) { 41 | debugf("do_readinode(%s, &ino, &vnode); failed", path); 42 | return rt; 43 | } 44 | 45 | if (uid != -1) { 46 | ext2_write_uid(&inode, uid); 47 | } 48 | if (gid != -1) { 49 | ext2_write_gid(&inode, gid); 50 | } 51 | 52 | inode.i_ctime = e2fs->now ? e2fs->now : time(NULL); 53 | 54 | rt = do_writeinode(e2fs, ino, &inode); 55 | if (rt) { 56 | debugf("do_writeinode(e2fs, ino, &inode); failed"); 57 | return -EIO; 58 | } 59 | 60 | debugf("leave"); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /fuse-ext2/op_create.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int do_modetoext2lag (mode_t mode) 24 | { 25 | if (S_ISREG(mode)) { 26 | return EXT2_FT_REG_FILE; 27 | } else if (S_ISDIR(mode)) { 28 | return EXT2_FT_DIR; 29 | } else if (S_ISCHR(mode)) { 30 | return EXT2_FT_CHRDEV; 31 | } else if (S_ISBLK(mode)) { 32 | return EXT2_FT_BLKDEV; 33 | } else if (S_ISFIFO(mode)) { 34 | return EXT2_FT_FIFO; 35 | } else if (S_ISSOCK(mode)) { 36 | return EXT2_FT_SOCK; 37 | } else if (S_ISLNK(mode)) { 38 | return EXT2_FT_SYMLINK; 39 | } 40 | return EXT2_FT_UNKNOWN; 41 | } 42 | 43 | static inline int old_valid_dev(dev_t dev) 44 | { 45 | return major(dev) < 256 && minor(dev) < 256; 46 | } 47 | 48 | static inline __u16 old_encode_dev(dev_t dev) 49 | { 50 | return (major(dev) << 8) | minor(dev); 51 | } 52 | 53 | static inline __u32 new_encode_dev(dev_t dev) 54 | { 55 | unsigned major_v = major(dev); 56 | unsigned minor_v = minor(dev); 57 | return (minor_v & 0xff) | (major_v << 8) | ((minor_v & ~0xff) << 12); 58 | } 59 | 60 | int do_create (ext2_filsys e2fs, const char *path, mode_t mode, dev_t dev, const char *fastsymlink) 61 | { 62 | int rt; 63 | time_t tm; 64 | errcode_t rc; 65 | 66 | char *p_path; 67 | char *r_path; 68 | 69 | ext2_ino_t ino; 70 | struct ext2_inode inode; 71 | ext2_ino_t n_ino; 72 | 73 | struct fuse_context *ctx; 74 | 75 | debugf("enter"); 76 | debugf("path = %s, mode: 0%o", path, mode); 77 | 78 | rt=do_check_split(path, &p_path, &r_path); 79 | 80 | debugf("parent: %s, child: %s", p_path, r_path); 81 | 82 | rt = do_readinode(e2fs, p_path, &ino, &inode); 83 | if (rt) { 84 | debugf("do_readinode(%s, &ino, &inode); failed", p_path); 85 | free_split(p_path, r_path); 86 | return rt; 87 | } 88 | 89 | rc = ext2fs_new_inode(e2fs, ino, mode, 0, &n_ino); 90 | if (rc) { 91 | debugf("ext2fs_new_inode(ep.fs, ino, mode, 0, &n_ino); failed"); 92 | free_split(p_path, r_path); 93 | return -ENOMEM; 94 | } 95 | 96 | do { 97 | debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", ino, r_path, n_ino, do_modetoext2lag(mode)); 98 | rc = ext2fs_link(e2fs, ino, r_path, n_ino, do_modetoext2lag(mode)); 99 | if (rc == EXT2_ET_DIR_NO_SPACE) { 100 | debugf("calling ext2fs_expand_dir(e2fs, &d)", ino); 101 | if (ext2fs_expand_dir(e2fs, ino)) { 102 | debugf("error while expanding directory %s (%d)", p_path, ino); 103 | free_split(p_path, r_path); 104 | return -ENOSPC; 105 | } 106 | } 107 | } while (rc == EXT2_ET_DIR_NO_SPACE); 108 | if (rc) { 109 | debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", ino, r_path, n_ino, do_modetoext2lag(mode)); 110 | free_split(p_path, r_path); 111 | return -EIO; 112 | } 113 | 114 | if (ext2fs_test_inode_bitmap(e2fs->inode_map, n_ino)) { 115 | debugf("inode already set"); 116 | } 117 | 118 | ext2fs_inode_alloc_stats2(e2fs, n_ino, +1, 0); 119 | memset(&inode, 0, sizeof(inode)); 120 | tm = e2fs->now ? e2fs->now : time(NULL); 121 | inode.i_mode = mode; 122 | inode.i_atime = inode.i_ctime = inode.i_mtime = tm; 123 | inode.i_links_count = 1; 124 | inode.i_size = 0; 125 | ctx = fuse_get_context(); 126 | if (ctx) { 127 | ext2_write_uid(&inode, ctx->uid); 128 | ext2_write_gid(&inode, ctx->gid); 129 | } 130 | if (e2fs->super->s_feature_incompat & 131 | EXT3_FEATURE_INCOMPAT_EXTENTS) { 132 | int i; 133 | struct ext3_extent_header *eh; 134 | 135 | eh = (struct ext3_extent_header *) &inode.i_block[0]; 136 | eh->eh_depth = 0; 137 | eh->eh_entries = 0; 138 | eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); 139 | i = (sizeof(inode.i_block) - sizeof(*eh)) / 140 | sizeof(struct ext3_extent); 141 | eh->eh_max = ext2fs_cpu_to_le16(i); 142 | inode.i_flags |= EXT4_EXTENTS_FL; 143 | } 144 | 145 | if (S_ISCHR(mode) || S_ISBLK(mode)) { 146 | if (old_valid_dev(dev)) 147 | inode.i_block[0]= ext2fs_cpu_to_le32(old_encode_dev(dev)); 148 | else 149 | inode.i_block[1]= ext2fs_cpu_to_le32(new_encode_dev(dev)); 150 | } 151 | 152 | if (S_ISLNK(mode) && fastsymlink != NULL) { 153 | inode.i_size = strlen(fastsymlink); 154 | strncpy((char *)&(inode.i_block[0]),fastsymlink, 155 | (EXT2_N_BLOCKS * sizeof(inode.i_block[0]))); 156 | } 157 | 158 | rc = ext2fs_write_new_inode(e2fs, n_ino, &inode); 159 | if (rc) { 160 | debugf("ext2fs_write_new_inode(e2fs, n_ino, &inode);"); 161 | free_split(p_path, r_path); 162 | return -EIO; 163 | } 164 | 165 | /* update parent dir */ 166 | rt = do_readinode(e2fs, p_path, &ino, &inode); 167 | if (rt) { 168 | debugf("do_readinode(%s, &ino, &inode); dailed", p_path); 169 | free_split(p_path, r_path); 170 | return -EIO; 171 | } 172 | inode.i_ctime = inode.i_mtime = tm; 173 | rc = do_writeinode(e2fs, ino, &inode); 174 | if (rc) { 175 | debugf("do_writeinode(e2fs, ino, &inode); failed"); 176 | free_split(p_path, r_path); 177 | return -EIO; 178 | } 179 | 180 | free_split(p_path, r_path); 181 | 182 | debugf("leave"); 183 | return 0; 184 | } 185 | 186 | int op_create (const char *path, mode_t mode, struct fuse_file_info *fi) 187 | { 188 | int rt; 189 | ext2_filsys e2fs = current_ext2fs(); 190 | 191 | debugf("enter"); 192 | debugf("path = %s, mode: 0%o", path, mode); 193 | 194 | if (op_open(path, fi) == 0) { 195 | debugf("leave"); 196 | return 0; 197 | } 198 | 199 | rt = do_create(e2fs, path, mode, 0, NULL); 200 | if (rt != 0) { 201 | return rt; 202 | } 203 | 204 | if (op_open(path, fi)) { 205 | debugf("op_open(path, fi); failed"); 206 | return -EIO; 207 | } 208 | 209 | debugf("leave"); 210 | return 0; 211 | } 212 | -------------------------------------------------------------------------------- /fuse-ext2/op_destroy.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | void op_destroy (void *userdata) 24 | { 25 | errcode_t rc; 26 | ext2_filsys e2fs = current_ext2fs(); 27 | 28 | debugf("enter"); 29 | rc = ext2fs_close(e2fs); 30 | if (rc) { 31 | debugf("Error while trying to close ext2 filesystem"); 32 | } 33 | e2fs = NULL; 34 | debugf("leave"); 35 | } 36 | -------------------------------------------------------------------------------- /fuse-ext2/op_fgetattr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_fgetattr (const char *path, struct stat *stbuf, struct fuse_file_info *fi) 24 | { 25 | int rt; 26 | ext2_ino_t ino; 27 | struct ext2_inode inode; 28 | ext2_filsys e2fs = current_ext2fs(); 29 | 30 | debugf("enter"); 31 | debugf("path = %s", path); 32 | 33 | rt = do_check(path); 34 | if (rt != 0) { 35 | debugf("do_check(%s); failed", path); 36 | return rt; 37 | } 38 | 39 | rt = do_readinode(e2fs, path, &ino, &inode); 40 | if (rt) { 41 | debugf("do_readinode(%s, &ino, &vnode); failed", path); 42 | return rt; 43 | } 44 | do_fillstatbuf(e2fs, ino, &inode, stbuf); 45 | 46 | debugf("path: %s, size: %d", path, stbuf->st_size); 47 | debugf("leave"); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /fuse-ext2/op_flush.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_flush (const char *path, struct fuse_file_info *fi) 24 | { 25 | errcode_t rc; 26 | ext2_file_t efile = EXT2FS_FILE(fi->fh); 27 | 28 | debugf("enter"); 29 | debugf("path = %s (%p)", path, efile); 30 | 31 | if (efile == NULL) { 32 | return -ENOENT; 33 | } 34 | 35 | rc = ext2fs_file_flush(efile); 36 | if (rc) { 37 | return -EIO; 38 | } 39 | 40 | debugf("leave"); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /fuse-ext2/op_fsync.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_fsync (const char *path, int datasync, struct fuse_file_info *fi) 24 | { 25 | errcode_t rc; 26 | ext2_filsys e2fs = current_ext2fs(); 27 | 28 | debugf("enter"); 29 | debugf("path = %s (%p)", path, fi); 30 | 31 | rc = ext2fs_flush(e2fs); 32 | if (rc) { 33 | return -EIO; 34 | } 35 | 36 | debugf("leave"); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /fuse-ext2/op_getattr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_getattr (const char *path, struct stat *stbuf) 24 | { 25 | int rt; 26 | ext2_ino_t ino; 27 | struct ext2_inode inode; 28 | ext2_filsys e2fs = current_ext2fs(); 29 | 30 | debugf("enter"); 31 | debugf("path = %s", path); 32 | 33 | rt = do_check(path); 34 | if (rt != 0) { 35 | debugf("do_check(%s); failed", path); 36 | return rt; 37 | } 38 | 39 | rt = do_readinode(e2fs, path, &ino, &inode); 40 | if (rt) { 41 | debugf("do_readinode(%s, &ino, &vnode); failed", path); 42 | return rt; 43 | } 44 | do_fillstatbuf(e2fs, ino, &inode, stbuf); 45 | 46 | debugf("path: %s, size: %d", path, stbuf->st_size); 47 | debugf("leave"); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /fuse-ext2/op_getxattr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief EXT2 getxattr support 4 | * 5 | * @date 14.01.2015 6 | * @author Alexander Kalmuk 7 | */ 8 | 9 | #include "fuse-ext2.h" 10 | 11 | #if !defined(ENOATTR) 12 | #define ENOATTR ENODATA 13 | #endif 14 | 15 | static int do_getxattr(ext2_filsys e2fs, struct ext2_inode *node, const char *name, 16 | char *value, size_t size); 17 | 18 | int op_getxattr(const char *path, const char *name, char *value, size_t size) { 19 | int rt; 20 | ext2_ino_t ino; 21 | struct ext2_inode inode; 22 | ext2_filsys e2fs = current_ext2fs(); 23 | 24 | debugf("enter"); 25 | debugf("path = %s", path); 26 | debugf("path = %s, %s, %p, %d", path, name, value, size); 27 | 28 | rt = do_check(path); 29 | if (rt != 0) { 30 | debugf("do_check(%s); failed", path); 31 | return rt; 32 | } 33 | 34 | rt = do_readinode(e2fs, path, &ino, &inode); 35 | if (rt) { 36 | debugf("do_readinode(%s, &ino, &inode); failed", path); 37 | return rt; 38 | } 39 | 40 | rt = do_getxattr(e2fs, &inode, name, value, size); 41 | if (rt < 0) { 42 | debugf("do_getxattr(e2fs, inode, %s, value, %d); failed", name, size); 43 | return rt; 44 | } 45 | 46 | debugf("leave"); 47 | return rt; 48 | } 49 | 50 | /** 51 | * Name is of format namespace:attribute. This function return namespace as @p name_index 52 | * and attribute as @p attr_name 53 | * 54 | * TODO support trusted, system and security attributes 55 | */ 56 | static int parse_name(const char *name, int *name_index, char **attr_name) { 57 | char namespace[16]; 58 | char *attr_name_str; 59 | 60 | memcpy(namespace, name, sizeof namespace); 61 | 62 | attr_name_str = strchr(namespace, '.'); 63 | if (!attr_name) { 64 | return -ENOTSUP; 65 | } else { 66 | *attr_name_str = 0; 67 | *attr_name = ++attr_name_str; 68 | } 69 | 70 | if (!strcmp(namespace, "user")) { 71 | *name_index = 1; 72 | return 0; 73 | } 74 | 75 | return -ENOTSUP; 76 | } 77 | 78 | static int do_getxattr(ext2_filsys e2fs, struct ext2_inode *node, const char *name, 79 | char *value, size_t size) { 80 | char *buf, *attr_start; 81 | struct ext2_ext_attr_entry *entry; 82 | char *entry_name, *value_name; 83 | int name_index; 84 | int res; 85 | 86 | res = parse_name(name, &name_index, &value_name); 87 | if (res < 0) { 88 | return res; 89 | } 90 | 91 | buf = malloc(e2fs->blocksize); 92 | if (!buf) { 93 | return -ENOMEM; 94 | } 95 | ext2fs_read_ext_attr(e2fs, node->i_file_acl, buf); 96 | 97 | attr_start = buf + sizeof(struct ext2_ext_attr_header); 98 | entry = (struct ext2_ext_attr_entry *) attr_start; 99 | res = -ENOATTR; 100 | 101 | while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { 102 | entry_name = (char *)entry + sizeof(struct ext2_ext_attr_entry); 103 | 104 | if (name_index == entry->e_name_index && 105 | entry->e_name_len == strlen(value_name)) { 106 | if (!strncmp(entry_name, value_name, entry->e_name_len)) { 107 | if (size > 0) { 108 | memcpy(value, buf + entry->e_value_offs, entry->e_value_size); 109 | } 110 | res = entry->e_value_size; 111 | break; 112 | } 113 | } 114 | entry = EXT2_EXT_ATTR_NEXT(entry); 115 | } 116 | 117 | free(buf); 118 | return res; 119 | } 120 | -------------------------------------------------------------------------------- /fuse-ext2/op_init.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | void * op_init (struct fuse_conn_info *conn) 24 | { 25 | errcode_t rc; 26 | struct fuse_context *cntx=fuse_get_context(); 27 | struct extfs_data *e2data=cntx->private_data; 28 | 29 | debugf("enter %s", e2data->device); 30 | 31 | rc = ext2fs_open(e2data->device, 32 | (e2data->readonly) ? 0 : EXT2_FLAG_RW, 33 | 0, 0, unix_io_manager, &e2data->e2fs); 34 | if (rc) { 35 | debugf("Error while trying to open %s", e2data->device); 36 | exit(1); 37 | } 38 | #if 1 39 | if (e2data->readonly != 1) 40 | #endif 41 | rc = ext2fs_read_bitmaps(e2data->e2fs); 42 | if (rc) { 43 | debugf("Error while reading bitmaps"); 44 | ext2fs_close(e2data->e2fs); 45 | exit(1); 46 | } 47 | debugf("FileSystem %s", (e2data->e2fs->flags & EXT2_FLAG_RW) ? "Read&Write" : "ReadOnly"); 48 | 49 | debugf("leave"); 50 | 51 | return e2data; 52 | } 53 | -------------------------------------------------------------------------------- /fuse-ext2/op_link.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_link (const char *source, const char *dest) 24 | { 25 | int rc; 26 | char *p_path; 27 | char *r_path; 28 | 29 | ext2_ino_t s_ino; 30 | ext2_ino_t d_ino; 31 | struct ext2_inode s_inode; 32 | struct ext2_inode d_inode; 33 | ext2_filsys e2fs = current_ext2fs(); 34 | 35 | debugf("source: %s, dest: %s", source, dest); 36 | 37 | rc = do_check(source); 38 | if (rc != 0) { 39 | debugf("do_check(%s); failed", source); 40 | return rc; 41 | } 42 | 43 | rc = do_check_split(dest, &p_path, &r_path); 44 | if (rc != 0) { 45 | debugf("do_check(%s); failed", dest); 46 | return rc; 47 | } 48 | 49 | debugf("parent: %s, child: %s", p_path, r_path); 50 | 51 | rc = do_readinode(e2fs, p_path, &d_ino, &d_inode); 52 | if (rc) { 53 | debugf("do_readinode(%s, &ino, &inode); failed", p_path); 54 | free_split(p_path, r_path); 55 | return rc; 56 | } 57 | 58 | rc = do_readinode(e2fs, source, &s_ino, &s_inode); 59 | if (rc) { 60 | debugf("do_readinode(%s, &s_ino, &s_inode); failed", p_path); 61 | free_split(p_path, r_path); 62 | return rc; 63 | } 64 | 65 | do { 66 | debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", d_ino, r_path, s_ino, do_modetoext2lag(s_inode.i_mode)); 67 | rc = ext2fs_link(e2fs, d_ino, r_path, s_ino, do_modetoext2lag(s_inode.i_mode)); 68 | if (rc == EXT2_ET_DIR_NO_SPACE) { 69 | debugf("calling ext2fs_expand_dir(e2fs, &d)", d_ino); 70 | if (ext2fs_expand_dir(e2fs, d_ino)) { 71 | debugf("error while expanding directory %s (%d)", p_path, d_ino); 72 | free_split(p_path, r_path); 73 | return -ENOSPC; 74 | } 75 | } 76 | } while (rc == EXT2_ET_DIR_NO_SPACE); 77 | if (rc) { 78 | debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", d_ino, r_path, s_ino, do_modetoext2lag(s_inode.i_mode)); 79 | free_split(p_path, r_path); 80 | return -EIO; 81 | } 82 | 83 | d_inode.i_mtime = d_inode.i_ctime = s_inode.i_ctime = e2fs->now ? e2fs->now : time(NULL); 84 | s_inode.i_links_count += 1; 85 | 86 | rc = do_writeinode(e2fs, s_ino, &s_inode); 87 | if (rc) { 88 | debugf("do_writeinode(e2fs, s_ino, &s_inode); failed"); 89 | free_split(p_path, r_path); 90 | return -EIO; 91 | } 92 | 93 | rc = do_writeinode(e2fs, d_ino, &d_inode); 94 | if (rc) { 95 | debugf("do_writeinode(e2fs, d_ino, &d_inode); failed"); 96 | free_split(p_path, r_path); 97 | return -EIO; 98 | } 99 | 100 | free_split(p_path, r_path); 101 | debugf("done"); 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /fuse-ext2/op_mkdir.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_mkdir (const char *path, mode_t mode) 24 | { 25 | int rt; 26 | time_t tm; 27 | errcode_t rc; 28 | 29 | char *p_path; 30 | char *r_path; 31 | 32 | ext2_ino_t ino; 33 | struct ext2_inode inode; 34 | 35 | struct fuse_context *ctx; 36 | 37 | ext2_filsys e2fs = current_ext2fs(); 38 | 39 | debugf("enter"); 40 | debugf("path = %s, mode: 0%o, dir:0%o", path, mode, LINUX_S_IFDIR); 41 | 42 | rt = do_check_split(path, &p_path ,&r_path); 43 | if (rt != 0) { 44 | debugf("do_check(%s); failed", path); 45 | return rt; 46 | } 47 | 48 | debugf("parent: %s, child: %s, pathmax: %d", p_path, r_path, PATH_MAX); 49 | 50 | rt = do_readinode(e2fs, p_path, &ino, &inode); 51 | if (rt) { 52 | debugf("do_readinode(%s, &ino, &inode); failed", p_path); 53 | free_split(p_path, r_path); 54 | return rt; 55 | } 56 | 57 | do { 58 | debugf("calling ext2fs_mkdir(e2fs, %d, 0, %s);", ino, r_path); 59 | rc = ext2fs_mkdir(e2fs, ino, 0, r_path); 60 | if (rc == EXT2_ET_DIR_NO_SPACE) { 61 | debugf("calling ext2fs_expand_dir(e2fs, &d)", ino); 62 | if (ext2fs_expand_dir(e2fs, ino)) { 63 | debugf("error while expanding directory %s (%d)", p_path, ino); 64 | free_split(p_path, r_path); 65 | return -ENOSPC; 66 | } 67 | } 68 | } while (rc == EXT2_ET_DIR_NO_SPACE); 69 | if (rc) { 70 | debugf("ext2fs_mkdir(e2fs, %d, 0, %s); failed (%d)", ino, r_path, rc); 71 | debugf("e2fs: %p, e2fs->inode_map: %p", e2fs, e2fs->inode_map); 72 | free_split(p_path, r_path); 73 | return -EIO; 74 | } 75 | 76 | rt = do_readinode(e2fs, path, &ino, &inode); 77 | if (rt) { 78 | debugf("do_readinode(%s, &ino, &inode); failed", path); 79 | free_split(p_path, r_path); 80 | return -EIO; 81 | } 82 | tm = e2fs->now ? e2fs->now : time(NULL); 83 | inode.i_mode = LINUX_S_IFDIR | mode; 84 | inode.i_ctime = inode.i_atime = inode.i_mtime = tm; 85 | ctx = fuse_get_context(); 86 | if (ctx) { 87 | ext2_write_uid(&inode, ctx->uid); 88 | ext2_write_gid(&inode, ctx->gid); 89 | } 90 | rc = do_writeinode(e2fs, ino, &inode); 91 | if (rc) { 92 | debugf("do_writeinode(e2fs, ino, &inode); failed"); 93 | free_split(p_path, r_path); 94 | return -EIO; 95 | } 96 | 97 | /* update parent dir */ 98 | rt = do_readinode(e2fs, p_path, &ino, &inode); 99 | if (rt) { 100 | debugf("do_readinode(%s, &ino, &inode); dailed", p_path); 101 | free_split(p_path, r_path); 102 | return -EIO; 103 | } 104 | inode.i_ctime = inode.i_mtime = tm; 105 | rc = do_writeinode(e2fs, ino, &inode); 106 | if (rc) { 107 | debugf("do_writeinode(e2fs, ino, &inode); failed"); 108 | free_split(p_path, r_path); 109 | return -EIO; 110 | } 111 | 112 | free_split(p_path, r_path); 113 | 114 | debugf("leave"); 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /fuse-ext2/op_mknod.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_mknod (const char *path, mode_t mode, dev_t dev) 24 | { 25 | int rt; 26 | ext2_filsys e2fs = current_ext2fs(); 27 | 28 | debugf("enter"); 29 | debugf("path = %s 0%o", path, mode); 30 | 31 | rt = do_create(e2fs, path, mode, dev, NULL); 32 | 33 | debugf("leave"); 34 | return rt; 35 | } 36 | -------------------------------------------------------------------------------- /fuse-ext2/op_open.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | ext2_file_t do_open (ext2_filsys e2fs, const char *path, int flags) 24 | { 25 | int rt; 26 | errcode_t rc; 27 | ext2_ino_t ino; 28 | ext2_file_t efile; 29 | struct ext2_inode inode; 30 | struct fuse_context *cntx = fuse_get_context(); 31 | struct extfs_data *e2data = cntx->private_data; 32 | 33 | debugf("enter"); 34 | debugf("path = %s", path); 35 | 36 | rt = do_check(path); 37 | if (rt != 0) { 38 | debugf("do_check(%s); failed", path); 39 | return NULL; 40 | } 41 | 42 | rt = do_readinode(e2fs, path, &ino, &inode); 43 | if (rt) { 44 | debugf("do_readinode(%s, &ino, &inode); failed", path); 45 | return NULL; 46 | } 47 | 48 | rc = ext2fs_file_open2( 49 | e2fs, 50 | ino, 51 | &inode, 52 | (((flags & O_ACCMODE) != 0) ? EXT2_FILE_WRITE : 0) | EXT2_FILE_SHARED_INODE, 53 | &efile); 54 | if (rc) { 55 | return NULL; 56 | } 57 | 58 | if (e2data->readonly == 0) { 59 | inode.i_atime = e2fs->now ? e2fs->now : time(NULL); 60 | rt = do_writeinode(e2fs, ino, &inode); 61 | if (rt) { 62 | debugf("do_writeinode(%s, &ino, &inode); failed", path); 63 | return NULL; 64 | } 65 | } 66 | 67 | debugf("leave"); 68 | return efile; 69 | } 70 | 71 | int op_open (const char *path, struct fuse_file_info *fi) 72 | { 73 | ext2_file_t efile; 74 | ext2_filsys e2fs = current_ext2fs(); 75 | 76 | debugf("enter"); 77 | debugf("path = %s", path); 78 | 79 | efile = do_open(e2fs, path, fi->flags); 80 | if (efile == NULL) { 81 | debugf("do_open(%s); failed", path); 82 | return -ENOENT; 83 | } 84 | fi->fh = (uint64_t) efile; 85 | 86 | debugf("leave"); 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /fuse-ext2/op_read.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) 24 | { 25 | __u64 pos; 26 | errcode_t rc; 27 | unsigned int bytes; 28 | ext2_file_t efile = EXT2FS_FILE(fi->fh); 29 | ext2_filsys e2fs = current_ext2fs(); 30 | 31 | debugf("enter"); 32 | debugf("path = %s", path); 33 | 34 | efile = do_open(e2fs, path, O_RDONLY); 35 | rc = ext2fs_file_llseek(efile, offset, SEEK_SET, &pos); 36 | if (rc) { 37 | do_release(efile); 38 | return -EINVAL; 39 | } 40 | 41 | rc = ext2fs_file_read(efile, buf, size, &bytes); 42 | if (rc) { 43 | do_release(efile); 44 | return -EIO; 45 | } 46 | do_release(efile); 47 | 48 | debugf("leave"); 49 | return bytes; 50 | } 51 | -------------------------------------------------------------------------------- /fuse-ext2/op_readdir.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | struct dir_walk_data { 24 | char *buf; 25 | fuse_fill_dir_t filler; 26 | }; 27 | 28 | //#define _USE_DIR_ITERATE2 1 29 | #if defined(_USE_DIR_ITERATE2) && (_USE_DIR_ITERATE2 == 1) 30 | static int walk_dir2 (ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent, int offset, int blocksize, char *buf, void *vpsid) 31 | { 32 | int res; 33 | int len; 34 | struct stat st; 35 | unsigned char type; 36 | if (dirent->name_len <= 0) { 37 | return 0; 38 | } 39 | struct dir_walk_data *psid = (struct dir_walk_data *) vpsid; 40 | memset(&st, 0, sizeof(st)); 41 | 42 | len = dirent->name_len & 0xff; 43 | dirent->name[len] = 0; // bug wraparound 44 | 45 | switch (dirent->name_len >> 8) { 46 | case EXT2_FT_UNKNOWN: type = DT_UNKNOWN; break; 47 | case EXT2_FT_REG_FILE: type = DT_REG; break; 48 | case EXT2_FT_DIR: type = DT_DIR; break; 49 | case EXT2_FT_CHRDEV: type = DT_CHR; break; 50 | case EXT2_FT_BLKDEV: type = DT_BLK; break; 51 | case EXT2_FT_FIFO: type = DT_FIFO; break; 52 | case EXT2_FT_SOCK: type = DT_SOCK; break; 53 | case EXT2_FT_SYMLINK: type = DT_LNK; break; 54 | default: type = DT_UNKNOWN; break; 55 | } 56 | if (type == DT_UNKNOWN) { 57 | return 0; 58 | } 59 | { 60 | int rc; 61 | struct ext2_inode inode; 62 | ext2_filsys e2fs = current_ext2fs(); 63 | rc = ext2fs_read_inode(e2fs, dirent->inode, &inode); 64 | if (rc) { 65 | debugf("ext2fs_read_inode(%d, &inode); failed", dirent->inode); 66 | return 0; 67 | } 68 | } 69 | st.st_ino = dirent->inode; 70 | st.st_mode = type << 12; 71 | debugf("%s %d %d %d", dirent->name, dirent->name_len & 0xff, dirent->name_len >> 8, type); 72 | res = psid->filler(psid->buf, dirent->name, &st, 0); 73 | if (res != 0) { 74 | return BLOCK_ABORT; 75 | } 76 | return 0; 77 | } 78 | #else 79 | static int walk_dir (struct ext2_dir_entry *de, int offset, int blocksize, char *buf, void *priv_data) 80 | { 81 | int ret; 82 | size_t flen; 83 | char *fname; 84 | struct dir_walk_data *b = priv_data; 85 | 86 | debugf("enter"); 87 | 88 | flen = de->name_len & 0xff; 89 | fname = (char *) malloc(sizeof(char) * (flen + 1)); 90 | if (fname == NULL) { 91 | debugf("s = (char *) malloc(sizeof(char) * (%d + 1)); failed", flen); 92 | return -ENOMEM; 93 | } 94 | snprintf(fname, flen + 1, "%s", de->name); 95 | debugf("b->filler(b->buf, %s, NULL, 0);", fname); 96 | ret = b->filler(b->buf, fname, NULL, 0); 97 | free(fname); 98 | 99 | debugf("leave"); 100 | return ret; 101 | } 102 | #endif 103 | 104 | int op_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) 105 | { 106 | int rt; 107 | errcode_t rc; 108 | ext2_ino_t ino; 109 | struct ext2_inode inode; 110 | struct dir_walk_data dwd={ 111 | .buf = buf, 112 | .filler = filler}; 113 | ext2_filsys e2fs = current_ext2fs(); 114 | 115 | debugf("enter"); 116 | debugf("path = %s", path); 117 | 118 | rt = do_readinode(e2fs, path, &ino, &inode); 119 | if (rt) { 120 | debugf("do_readinode(%s, &ino, &inode); failed", path); 121 | return rt; 122 | } 123 | 124 | #if defined(_USE_DIR_ITERATE2) && (_USE_DIR_ITERATE2 == 1) 125 | rc = ext2fs_dir_iterate2(e2fs,ino, DIRENT_FLAG_INCLUDE_EMPTY, NULL, walk_dir2, &dwd); 126 | #else 127 | rc = ext2fs_dir_iterate(e2fs, ino, 0, NULL, walk_dir, &dwd); 128 | #endif 129 | 130 | if (rc) { 131 | debugf("Error while trying to ext2fs_dir_iterate %s", path); 132 | return -EIO; 133 | } 134 | 135 | debugf("leave"); 136 | return 0; 137 | } 138 | -------------------------------------------------------------------------------- /fuse-ext2/op_readlink.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_readlink (const char *path, char *buf, size_t size) 24 | { 25 | int rt; 26 | size_t s; 27 | errcode_t rc; 28 | ext2_ino_t ino; 29 | char *b = NULL; 30 | char *pathname; 31 | struct ext2_inode inode; 32 | ext2_filsys e2fs = current_ext2fs(); 33 | 34 | debugf("enter"); 35 | debugf("path = %s", path); 36 | 37 | rt = do_readinode(e2fs, path, &ino, &inode); 38 | if (rt) { 39 | debugf("do_readinode(%s, &ino, &inode); failed", path); 40 | return rt; 41 | } 42 | 43 | if (!LINUX_S_ISLNK(inode.i_mode)) { 44 | debugf("%s is not a link", path); 45 | return -EINVAL; 46 | } 47 | 48 | if (ext2fs_inode_data_blocks(e2fs, &inode)) { 49 | rc = ext2fs_get_mem(EXT2_BLOCK_SIZE(e2fs->super), &b); 50 | if (rc) { 51 | debugf("ext2fs_get_mem(EXT2_BLOCK_SIZE(e2fs->super), &b); failed"); 52 | return -ENOMEM; 53 | } 54 | rc = io_channel_read_blk(e2fs->io, inode.i_block[0], 1, b); 55 | if (rc) { 56 | ext2fs_free_mem(&b); 57 | debugf("io_channel_read_blk(e2fs->io, inode.i_block[0], 1, b); failed"); 58 | return -EIO; 59 | } 60 | pathname = b; 61 | } else { 62 | pathname = (char *) &(inode.i_block[0]); 63 | } 64 | 65 | debugf("pathname: %s", pathname); 66 | 67 | s = (size < strlen(pathname) + 1) ? size : strlen(pathname) + 1; 68 | snprintf(buf, s, "%s", pathname); 69 | 70 | if (b) { 71 | ext2fs_free_mem(&b); 72 | } 73 | 74 | debugf("leave"); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /fuse-ext2/op_release.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int do_release (ext2_file_t efile) 24 | { 25 | errcode_t rc; 26 | 27 | debugf("enter"); 28 | debugf("path = (%p)", efile); 29 | 30 | if (efile == NULL) { 31 | return -ENOENT; 32 | } 33 | rc = ext2fs_file_close(efile); 34 | if (rc) { 35 | return -EIO; 36 | } 37 | 38 | debugf("leave"); 39 | return 0; 40 | } 41 | 42 | int op_release (const char *path, struct fuse_file_info *fi) 43 | { 44 | int rt; 45 | ext2_file_t efile = (ext2_file_t) (unsigned long) fi->fh; 46 | 47 | debugf("enter"); 48 | debugf("path = %s (%p)", path, efile); 49 | rt = do_release(efile); 50 | if (rt != 0) { 51 | debugf("do_release() failed"); 52 | return rt; 53 | } 54 | 55 | debugf("leave"); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /fuse-ext2/op_rename.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | static int fix_dotdot_proc (ext2_ino_t dir EXT2FS_ATTR((unused)), 24 | int entry EXT2FS_ATTR((unused)), 25 | struct ext2_dir_entry *dirent, 26 | int offset EXT2FS_ATTR((unused)), 27 | int blocksize EXT2FS_ATTR((unused)), 28 | char *buf EXT2FS_ATTR((unused)), void *private) 29 | { 30 | ext2_ino_t *p_dotdot = (ext2_ino_t *) private; 31 | 32 | debugf("enter"); 33 | debugf("walking on: %s", dirent->name); 34 | 35 | if ((dirent->name_len & 0xFF) == 2 && strncmp(dirent->name, "..", 2) == 0) { 36 | dirent->inode = *p_dotdot; 37 | 38 | debugf("leave (found '..')"); 39 | return DIRENT_ABORT | DIRENT_CHANGED; 40 | } else { 41 | debugf("leave"); 42 | return 0; 43 | } 44 | } 45 | 46 | static int do_fix_dotdot (ext2_filsys e2fs, ext2_ino_t ino, ext2_ino_t dotdot) 47 | { 48 | errcode_t rc; 49 | 50 | debugf("enter"); 51 | rc = ext2fs_dir_iterate2(e2fs, ino, DIRENT_FLAG_INCLUDE_EMPTY, 52 | 0, fix_dotdot_proc, &dotdot); 53 | if (rc) { 54 | debugf("while iterating over directory"); 55 | return -EIO; 56 | } 57 | debugf("leave"); 58 | return 0; 59 | } 60 | 61 | int op_rename (const char *source, const char *dest) 62 | { 63 | int rt; 64 | errcode_t rc; 65 | 66 | char *p_src; 67 | char *r_src; 68 | char *p_dest; 69 | char *r_dest; 70 | 71 | ext2_ino_t src_ino; 72 | ext2_ino_t dest_ino; 73 | ext2_ino_t d_src_ino; 74 | ext2_ino_t d_dest_ino; 75 | struct ext2_inode src_inode; 76 | struct ext2_inode dest_inode; 77 | struct ext2_inode d_src_inode; 78 | struct ext2_inode d_dest_inode; 79 | ext2_filsys e2fs = current_ext2fs(); 80 | 81 | debugf("source: %s, dest: %s", source, dest); 82 | 83 | rt = do_check_split(source, &p_src, &r_src); 84 | if (rt != 0) { 85 | debugf("do_check(%s); failed", source); 86 | return rt; 87 | } 88 | 89 | debugf("src_parent: %s, src_child: %s", p_src, r_src); 90 | 91 | rt = do_check_split(dest, &p_dest, &r_dest); 92 | if (rt != 0) { 93 | debugf("do_check(%s); failed", dest); 94 | return rt; 95 | } 96 | 97 | debugf("dest_parent: %s, dest_child: %s", p_dest, r_dest); 98 | 99 | rt = do_readinode(e2fs, p_src, &d_src_ino, &d_src_inode); 100 | if (rt != 0) { 101 | debugf("do_readinode(%s, &d_src_ino, &d_src_inode); failed", p_src); 102 | goto out; 103 | } 104 | 105 | rt = do_readinode(e2fs, p_dest, &d_dest_ino, &d_dest_inode); 106 | if (rt != 0) { 107 | debugf("do_readinode(%s, &d_dest_ino, &d_dest_inode); failed", p_dest); 108 | goto out; 109 | } 110 | 111 | rt = do_readinode(e2fs, source, &src_ino, &src_inode); 112 | if (rt != 0) { 113 | debugf("do_readinode(%s, &src_ino, &src_inode); failed", p_dest); 114 | goto out; 115 | } 116 | 117 | rt = do_readinode(e2fs, dest, &dest_ino, &dest_inode); 118 | if (rt != 0 && rt != -ENOENT) { 119 | debugf("do_readinode(%s, &dest_ino, &dest_inode); failed", dest); 120 | goto out; 121 | } 122 | 123 | /* If oldpath and newpath are existing hard links referring to the same 124 | * file, then rename() does nothing, and returns a success status. 125 | */ 126 | if (rt == 0 && src_ino == dest_ino) { 127 | goto out; 128 | } 129 | 130 | /* EINVAL: 131 | * The new pathname contained a path prefix of the old, this should be checked by fuse 132 | */ 133 | if (rt == 0) { 134 | if (LINUX_S_ISDIR(dest_inode.i_mode)) { 135 | /* EISDIR: 136 | * newpath is an existing directory, but oldpath is not a directory. 137 | */ 138 | if (!(LINUX_S_ISDIR(src_inode.i_mode))) { 139 | debugf("newpath is dir && oldpath is not a dir -> EISDIR"); 140 | rt = -EISDIR; 141 | goto out; 142 | } 143 | /* ENOTEMPTY: 144 | * newpath is a non-empty directory 145 | */ 146 | rt = do_check_empty_dir(e2fs, dest_ino); 147 | if (rt != 0) { 148 | debugf("do_check_empty_dir dest %s failed",dest); 149 | goto out; 150 | } 151 | } 152 | /* ENOTDIR: 153 | * oldpath is a directory, and newpath exists but is not a directory 154 | */ 155 | if (LINUX_S_ISDIR(src_inode.i_mode) && 156 | !(LINUX_S_ISDIR(dest_inode.i_mode))) { 157 | debugf("oldpath is dir && newpath is not a dir -> ENOTDIR"); 158 | rt = -ENOTDIR; 159 | goto out; 160 | } 161 | 162 | /* Step 1: if destination exists: delete it */ 163 | if (LINUX_S_ISDIR(dest_inode.i_mode)) { 164 | rc = op_rmdir(dest); 165 | } else { 166 | rc = op_unlink(dest); 167 | } 168 | if (rc) { 169 | debugf("do_writeinode(e2fs, ino, inode); failed"); 170 | goto out; 171 | } 172 | rt = do_readinode(e2fs, p_dest, &d_dest_ino, &d_dest_inode); 173 | if (rt != 0) { 174 | debugf("do_readinode(%s, &d_dest_ino, &d_dest_inode); failed", p_dest); 175 | goto out; 176 | } 177 | } 178 | 179 | /* Step 2: add the link */ 180 | do { 181 | debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", d_dest_ino, r_dest, src_ino, do_modetoext2lag(src_inode.i_mode)); 182 | rc = ext2fs_link(e2fs, d_dest_ino, r_dest, src_ino, do_modetoext2lag(src_inode.i_mode)); 183 | if (rc == EXT2_ET_DIR_NO_SPACE) { 184 | debugf("calling ext2fs_expand_dir(e2fs, &d)", src_ino); 185 | if (ext2fs_expand_dir(e2fs, d_dest_ino)) { 186 | debugf("error while expanding directory %s (%d)", p_dest, d_dest_ino); 187 | rt = -ENOSPC; 188 | goto out; 189 | } 190 | /* ext2fs_expand_dir changes d_dest_inode */ 191 | rt = do_readinode(e2fs, p_dest, &d_dest_ino, &d_dest_inode); 192 | if (rt != 0) { 193 | debugf("do_readinode(%s, &d_dest_ino, &d_dest_inode); failed", p_dest); 194 | goto out; 195 | } 196 | } 197 | } while (rc == EXT2_ET_DIR_NO_SPACE); 198 | if (rc != 0) { 199 | debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", d_dest_ino, r_dest, src_ino, do_modetoext2lag(src_inode.i_mode)); 200 | rt = -EIO; 201 | goto out; 202 | } 203 | 204 | /* Special case: if moving dir across different parents fix counters and '..' */ 205 | if (LINUX_S_ISDIR(src_inode.i_mode) && d_src_ino != d_dest_ino) { 206 | d_dest_inode.i_links_count++; 207 | if (d_src_inode.i_links_count > 1) { 208 | d_src_inode.i_links_count--; 209 | } 210 | rc = do_writeinode(e2fs, d_src_ino, &d_src_inode); 211 | if (rc != 0) { 212 | debugf("do_writeinode(e2fs, src_ino, &src_inode); failed"); 213 | rt = -EIO; 214 | goto out; 215 | } 216 | rt = do_fix_dotdot(e2fs, src_ino, d_dest_ino); 217 | if (rt != 0) { 218 | debugf("do_fix_dotdot failed"); 219 | goto out; 220 | } 221 | } 222 | 223 | /* utimes and inodes update */ 224 | d_dest_inode.i_mtime = d_dest_inode.i_ctime = src_inode.i_ctime = e2fs->now ? e2fs->now : time(NULL); 225 | rt = do_writeinode(e2fs, d_dest_ino, &d_dest_inode); 226 | if (rt != 0) { 227 | debugf("do_writeinode(e2fs, d_dest_ino, &d_dest_inode); failed"); 228 | goto out; 229 | } 230 | rt = do_writeinode(e2fs, src_ino, &src_inode); 231 | if (rt != 0) { 232 | debugf("do_writeinode(e2fs, src_ino, &src_inode); failed"); 233 | goto out; 234 | } 235 | debugf("done"); 236 | 237 | /* Step 3: delete the source */ 238 | 239 | rc = ext2fs_unlink(e2fs, d_src_ino, r_src, src_ino, 0); 240 | if (rc) { 241 | debugf("while unlinking src ino %d", (int) src_ino); 242 | rt = -EIO; 243 | goto out; 244 | } 245 | 246 | out: free_split(p_src, r_src); 247 | free_split(p_dest, r_dest); 248 | return rt; 249 | } 250 | -------------------------------------------------------------------------------- /fuse-ext2/op_rmdir.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | struct rmdir_st { 24 | ext2_ino_t parent; 25 | int empty; 26 | }; 27 | 28 | static int rmdir_proc (ext2_ino_t dir EXT2FS_ATTR((unused)), 29 | int entry EXT2FS_ATTR((unused)), 30 | struct ext2_dir_entry *dirent, 31 | int offset EXT2FS_ATTR((unused)), 32 | int blocksize EXT2FS_ATTR((unused)), 33 | char *buf EXT2FS_ATTR((unused)), void *private) 34 | { 35 | int *p_empty= (int *) private; 36 | 37 | debugf("enter"); 38 | debugf("walking on: %s", dirent->name); 39 | 40 | if (dirent->inode == 0 || 41 | (((dirent->name_len & 0xFF) == 1) && (dirent->name[0] == '.')) || 42 | (((dirent->name_len & 0xFF) == 2) && (dirent->name[0] == '.') && 43 | (dirent->name[1] == '.'))) { 44 | debugf("leave"); 45 | return 0; 46 | } 47 | *p_empty = 0; 48 | debugf("leave (not empty)"); 49 | return 0; 50 | } 51 | 52 | int do_check_empty_dir(ext2_filsys e2fs, ext2_ino_t ino) 53 | { 54 | errcode_t rc; 55 | int empty = 1; 56 | 57 | rc = ext2fs_dir_iterate2(e2fs, ino, 0, 0, rmdir_proc, &empty); 58 | if (rc) { 59 | debugf("while iterating over directory"); 60 | return -EIO; 61 | } 62 | 63 | if (empty == 0) { 64 | debugf("directory not empty"); 65 | return -ENOTEMPTY; 66 | } 67 | 68 | return 0; 69 | } 70 | 71 | int op_rmdir (const char *path) 72 | { 73 | int rt; 74 | errcode_t rc; 75 | 76 | char *p_path; 77 | char *r_path; 78 | 79 | ext2_ino_t p_ino; 80 | struct ext2_inode p_inode; 81 | ext2_ino_t r_ino; 82 | struct ext2_inode r_inode; 83 | 84 | ext2_filsys e2fs = current_ext2fs(); 85 | 86 | debugf("enter"); 87 | debugf("path = %s", path); 88 | 89 | rt = do_check_split(path, &p_path, &r_path); 90 | if (rt != 0) { 91 | debugf("do_check_split: failed"); 92 | return rt; 93 | } 94 | 95 | debugf("parent: %s, child: %s", p_path, r_path); 96 | 97 | rt = do_readinode(e2fs, p_path, &p_ino, &p_inode); 98 | if (rt) { 99 | debugf("do_readinode(%s, &p_ino, &p_inode); failed", p_path); 100 | free_split(p_path, r_path); 101 | return rt; 102 | } 103 | rt = do_readinode(e2fs, path, &r_ino, &r_inode); 104 | if (rt) { 105 | debugf("do_readinode(%s, &r_ino, &r_inode); failed", path); 106 | free_split(p_path, r_path); 107 | return rt; 108 | 109 | } 110 | if (!LINUX_S_ISDIR(r_inode.i_mode)) { 111 | debugf("%s is not a directory", path); 112 | free_split(p_path, r_path); 113 | return -ENOTDIR; 114 | } 115 | if (r_ino == EXT2_ROOT_INO) { 116 | debugf("root dir cannot be removed", path); 117 | free_split(p_path, r_path); 118 | return -EIO; 119 | } 120 | 121 | rt = do_check_empty_dir(e2fs, r_ino); 122 | if (rt) { 123 | debugf("do_check_empty_dir filed"); 124 | free_split(p_path, r_path); 125 | return rt; 126 | } 127 | 128 | rc = ext2fs_unlink(e2fs, p_ino, r_path, r_ino, 0); 129 | if (rc) { 130 | debugf("while unlinking ino %d", (int) r_ino); 131 | free_split(p_path, r_path); 132 | return -EIO; 133 | } 134 | 135 | rt = do_killfilebyinode(e2fs, r_ino, &r_inode); 136 | if (rt) { 137 | debugf("do_killfilebyinode(r_ino, &r_inode); failed"); 138 | free_split(p_path, r_path); 139 | return rt; 140 | } 141 | 142 | rt = do_readinode(e2fs, p_path, &p_ino, &p_inode); 143 | if (rt) { 144 | debugf("do_readinode(p_path, &p_ino, &p_inode); failed"); 145 | free_split(p_path, r_path); 146 | return rt; 147 | } 148 | if (p_inode.i_links_count > 1) { 149 | p_inode.i_links_count--; 150 | } 151 | p_inode.i_mtime = e2fs->now ? e2fs->now : time(NULL); 152 | p_inode.i_ctime = e2fs->now ? e2fs->now : time(NULL); 153 | rc = do_writeinode(e2fs, p_ino, &p_inode); 154 | if (rc) { 155 | debugf("do_writeinode(e2fs, ino, inode); failed"); 156 | free_split(p_path, r_path); 157 | return -EIO; 158 | } 159 | 160 | free_split(p_path, r_path); 161 | 162 | debugf("leave"); 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /fuse-ext2/op_statfs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | static int test_root (unsigned int a, unsigned int b) 24 | { 25 | while (1) { 26 | if (a < b) { 27 | return 0; 28 | } 29 | if (a == b) { 30 | return 1; 31 | } 32 | if (a % b) { 33 | return 0; 34 | } 35 | a = a / b; 36 | } 37 | } 38 | 39 | static int ext2_group_spare (int group) 40 | { 41 | if (group <= 1) { 42 | return 1; 43 | } 44 | return (test_root(group, 3) || test_root(group, 5) || test_root(group, 7)); 45 | } 46 | 47 | static int ext2_bg_has_super (ext2_filsys e2fs, int group) 48 | { 49 | if (EXT2_HAS_RO_COMPAT_FEATURE(e2fs->super, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) && 50 | !ext2_group_spare(group)) { 51 | return 0; 52 | } 53 | return 1; 54 | } 55 | 56 | static int ext2_bg_num_gdb (ext2_filsys e2fs, int group) 57 | { 58 | if (EXT2_HAS_RO_COMPAT_FEATURE(e2fs->super, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) && 59 | !ext2_group_spare(group)) { 60 | return 0; 61 | } 62 | return 1; 63 | } 64 | 65 | #define EXT2_BLOCKS_COUNT(s) ((s)->s_blocks_count | ((__u64) (s)->s_blocks_count_hi << 32)) 66 | #define EXT2_RBLOCKS_COUNT(s) ((s)->s_r_blocks_count | ((__u64) (s)->s_r_blocks_count_hi << 32)) 67 | #define EXT2_FBLOCKS_COUNT(s) ((s)->s_free_blocks_count | ((__u64) (s)->s_free_blocks_hi << 32)) 68 | 69 | int op_statfs (const char *path, struct statvfs *buf) 70 | { 71 | unsigned long long i; 72 | unsigned long long s_gdb_count = 0; 73 | unsigned long long s_groups_count = 0; 74 | unsigned long long s_itb_per_group = 0; 75 | unsigned long long s_overhead_last = 0; 76 | unsigned long long s_inodes_per_block = 0; 77 | 78 | ext2_filsys e2fs = current_ext2fs(); 79 | 80 | debugf("enter"); 81 | 82 | memset(buf, 0, sizeof(struct statvfs)); 83 | 84 | if (e2fs->super->s_default_mount_opts & EXT2_MOUNT_MINIX_DF) { 85 | s_overhead_last = 0; 86 | } else { 87 | s_overhead_last = e2fs->super->s_first_data_block; 88 | s_groups_count = ((EXT2_BLOCKS_COUNT(e2fs->super) - e2fs->super->s_first_data_block - 1) / e2fs->super->s_blocks_per_group) + 1; 89 | s_gdb_count = (s_groups_count + EXT2_DESC_PER_BLOCK(e2fs->super) - 1) / EXT2_DESC_PER_BLOCK(e2fs->super); 90 | for (i = 0; i < s_groups_count; i++) { 91 | s_overhead_last += ext2_bg_has_super(e2fs, i) + ((ext2_bg_num_gdb(e2fs, i) == 0) ? 0 : s_gdb_count); 92 | } 93 | s_inodes_per_block = EXT2_BLOCK_SIZE(e2fs->super) / EXT2_INODE_SIZE(e2fs->super); 94 | s_itb_per_group = e2fs->super->s_inodes_per_group / s_inodes_per_block; 95 | s_overhead_last += (s_groups_count * (2 + s_itb_per_group)); 96 | } 97 | buf->f_bsize = EXT2_BLOCK_SIZE(e2fs->super); 98 | buf->f_frsize = EXT2_FRAG_SIZE(e2fs->super); 99 | buf->f_blocks = EXT2_BLOCKS_COUNT(e2fs->super) - s_overhead_last; 100 | buf->f_bfree = EXT2_FBLOCKS_COUNT(e2fs->super); 101 | if (EXT2_FBLOCKS_COUNT(e2fs->super) < EXT2_RBLOCKS_COUNT(e2fs->super)) { 102 | buf->f_bavail = 0; 103 | } else { 104 | buf->f_bavail = EXT2_FBLOCKS_COUNT(e2fs->super) - EXT2_RBLOCKS_COUNT(e2fs->super); 105 | } 106 | buf->f_files = e2fs->super->s_inodes_count; 107 | buf->f_ffree = e2fs->super->s_free_inodes_count; 108 | buf->f_favail = e2fs->super->s_free_inodes_count; 109 | buf->f_namemax = EXT2_NAME_LEN; 110 | 111 | debugf("leave"); 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /fuse-ext2/op_symlink.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_symlink (const char *sourcename, const char *destname) 24 | { 25 | int rt; 26 | size_t wr; 27 | ext2_file_t efile; 28 | ext2_filsys e2fs = current_ext2fs(); 29 | int sourcelen = strlen(sourcename); 30 | 31 | debugf("enter"); 32 | debugf("source: %s, dest: %s", sourcename, destname); 33 | 34 | /* a short symlink is stored in the inode (recycling the i_block array) */ 35 | if (sourcelen < (EXT2_N_BLOCKS * sizeof(__u32))) { 36 | rt = do_create(e2fs, destname, LINUX_S_IFLNK | 0777, 0, sourcename); 37 | if (rt != 0) { 38 | debugf("do_create(%s, LINUX_S_IFLNK | 0777, FAST); failed", destname); 39 | return rt; 40 | } 41 | } else { 42 | rt = do_create(e2fs, destname, LINUX_S_IFLNK | 0777, 0, NULL); 43 | if (rt != 0) { 44 | debugf("do_create(%s, LINUX_S_IFLNK | 0777); failed", destname); 45 | return rt; 46 | } 47 | efile = do_open(e2fs, destname, O_WRONLY); 48 | if (efile == NULL) { 49 | debugf("do_open(%s); failed", destname); 50 | return -EIO; 51 | } 52 | wr = do_write(efile, sourcename, sourcelen, 0); 53 | if (wr != strlen(sourcename)) { 54 | debugf("do_write(efile, %s, %d, 0); failed", sourcename, strlen(sourcename) + 1); 55 | return -EIO; 56 | } 57 | rt = do_release(efile); 58 | if (rt != 0) { 59 | debugf("do_release(efile); failed"); 60 | return rt; 61 | } 62 | } 63 | debugf("leave"); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /fuse-ext2/op_truncate.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_truncate (const char *path, off_t length) 24 | { 25 | int rt; 26 | errcode_t rc; 27 | ext2_ino_t ino; 28 | struct ext2_inode inode; 29 | ext2_file_t efile; 30 | ext2_filsys e2fs = current_ext2fs(); 31 | 32 | debugf("enter"); 33 | debugf("path = %s", path); 34 | 35 | rt = do_check(path); 36 | if (rt != 0) { 37 | debugf("do_check(%s); failed", path); 38 | return rt; 39 | } 40 | efile = do_open(e2fs, path, O_WRONLY); 41 | if (efile == NULL) { 42 | debugf("do_open(%s); failed", path); 43 | return -ENOENT; 44 | } 45 | 46 | rc = ext2fs_file_set_size2(efile, length); 47 | if (rc) { 48 | do_release(efile); 49 | debugf("ext2fs_file_set_size(efile, %d); failed", length); 50 | if (rc == EXT2_ET_FILE_TOO_BIG) { 51 | return -EFBIG; 52 | } 53 | return -EIO; 54 | } 55 | 56 | rt = do_readinode(e2fs, path, &ino, &inode); 57 | if (rt) { 58 | debugf("do_readinode(%s, &ino, &vnode); failed", path); 59 | do_release(efile); 60 | return rt; 61 | } 62 | inode.i_ctime = e2fs->now ? e2fs->now : time(NULL); 63 | inode.i_mtime = e2fs->now ? e2fs->now : time(NULL); 64 | rt = do_writeinode(e2fs, ino, &inode); 65 | if (rt) { 66 | debugf("do_writeinode(e2fs, ino, &inode); failed"); 67 | do_release(efile); 68 | return -EIO; 69 | } 70 | 71 | rt = do_release(efile); 72 | if (rt != 0) { 73 | debugf("do_release(efile); failed"); 74 | return rt; 75 | } 76 | 77 | debugf("leave"); 78 | return 0; 79 | } 80 | 81 | int op_ftruncate (const char *path, off_t length, struct fuse_file_info *fi) 82 | { 83 | (void) fi; 84 | return op_truncate(path, length); 85 | } 86 | -------------------------------------------------------------------------------- /fuse-ext2/op_unlink.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_unlink (const char *path) 24 | { 25 | int rt; 26 | errcode_t rc; 27 | 28 | char *p_path; 29 | char *r_path; 30 | 31 | ext2_ino_t p_ino; 32 | ext2_ino_t r_ino; 33 | struct ext2_inode p_inode; 34 | struct ext2_inode r_inode; 35 | 36 | ext2_filsys e2fs = current_ext2fs(); 37 | 38 | debugf("enter"); 39 | debugf("path = %s", path); 40 | 41 | rt = do_check(path); 42 | if (rt != 0) { 43 | debugf("do_check(%s); failed", path); 44 | return rt; 45 | } 46 | 47 | rt = do_check_split(path, &p_path, &r_path); 48 | if (rt != 0) { 49 | debugf("do_check_split: failed"); 50 | return rt; 51 | } 52 | 53 | debugf("parent: %s, child: %s", p_path, r_path); 54 | 55 | rt = do_readinode(e2fs, p_path, &p_ino, &p_inode); 56 | if (rt) { 57 | debugf("do_readinode(%s, &p_ino, &p_inode); failed", path); 58 | free_split(p_path, r_path); 59 | return rt; 60 | } 61 | rt = do_readinode(e2fs, path, &r_ino, &r_inode); 62 | if (rt) { 63 | debugf("do_readinode(%s, &r_ino, &r_inode); failed", path); 64 | free_split(p_path, r_path); 65 | return rt; 66 | } 67 | 68 | if (LINUX_S_ISDIR(r_inode.i_mode)) { 69 | debugf("%s is a directory", path); 70 | free_split(p_path, r_path); 71 | return -EISDIR; 72 | } 73 | 74 | rc = ext2fs_unlink(e2fs, p_ino, r_path, r_ino, 0); 75 | if (rc) { 76 | debugf("ext2fs_unlink(e2fs, %d, %s, %d, 0); failed", p_ino, r_path, r_ino); 77 | free_split(p_path, r_path); 78 | return -EIO; 79 | } 80 | 81 | p_inode.i_ctime = p_inode.i_mtime = e2fs->now ? e2fs->now : time(NULL); 82 | rt = do_writeinode(e2fs, p_ino, &p_inode); 83 | if (rt) { 84 | debugf("do_writeinode(e2fs, p_ino, &p_inode); failed"); 85 | free_split(p_path, r_path); 86 | return -EIO; 87 | } 88 | 89 | if (r_inode.i_links_count > 0) { 90 | r_inode.i_links_count -= 1; 91 | } 92 | r_inode.i_ctime = e2fs->now ? e2fs->now : time(NULL); 93 | rc = do_writeinode(e2fs, r_ino, &r_inode); 94 | if (rc) { 95 | debugf("do_writeinode(e2fs, &r_ino, &r_inode); failed"); 96 | free_split(p_path, r_path); 97 | return -EIO; 98 | } 99 | 100 | free_split(p_path, r_path); 101 | debugf("leave"); 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /fuse-ext2/op_utimens.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | int op_utimens (const char *path, const struct timespec tv[2]) 24 | { 25 | int rt; 26 | ext2_ino_t ino; 27 | struct ext2_inode inode; 28 | ext2_filsys e2fs = current_ext2fs(); 29 | 30 | debugf("enter"); 31 | debugf("path = %s", path); 32 | 33 | rt = do_check(path); 34 | if (rt != 0) { 35 | debugf("do_check(%s); failed", path); 36 | return rt; 37 | } 38 | 39 | rt = do_readinode(e2fs, path, &ino, &inode); 40 | if (rt) { 41 | debugf("do_readinode(%s, &ino, &vnode); failed", path); 42 | return rt; 43 | } 44 | 45 | if (tv[0].tv_nsec != UTIME_OMIT) 46 | inode.i_atime = tv[0].tv_sec; 47 | if (tv[1].tv_nsec != UTIME_OMIT) 48 | inode.i_mtime = tv[1].tv_sec; 49 | 50 | rt = do_writeinode(e2fs, ino, &inode); 51 | if (rt) { 52 | debugf("do_writeinode(e2fs, ino, &inode); failed"); 53 | return -EIO; 54 | } 55 | 56 | debugf("leave"); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /fuse-ext2/op_write.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2008-2015 Alper Akcan 3 | * Copyright (c) 2009 Renzo Davoli 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program (in the main directory of the fuse-ext2 17 | * distribution in the file COPYING); if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include "fuse-ext2.h" 22 | 23 | size_t do_write (ext2_file_t efile, const char *buf, size_t size, off_t offset) 24 | { 25 | int rt; 26 | const char *tmp; 27 | unsigned int wr; 28 | unsigned long long npos; 29 | unsigned long long fsize; 30 | unsigned long long wsize; 31 | 32 | debugf("enter"); 33 | 34 | rt = ext2fs_file_get_lsize(efile, &fsize); 35 | if (rt != 0) { 36 | debugf("ext2fs_file_get_lsize(efile, &fsize); failed"); 37 | return -EIO; 38 | } 39 | 40 | rt = ext2fs_file_llseek(efile, offset, SEEK_SET, &npos); 41 | if (rt) { 42 | debugf("ext2fs_file_lseek(efile, %lld, SEEK_SET, &npos); failed", offset); 43 | return rt; 44 | } 45 | 46 | for (rt = 0, wr = 0, tmp = buf, wsize = 0; size > 0 && rt == 0; size -= wr, wsize += wr, tmp += wr) { 47 | rt = ext2fs_file_write(efile, tmp, size, &wr); 48 | debugf("rt: %d, size: %u, written: %u", rt, size, wr); 49 | } 50 | if (rt != 0 && rt != EXT2_ET_BLOCK_ALLOC_FAIL) { 51 | debugf("ext2fs_file_write(edile, tmp, size, &wr); failed"); 52 | return -EIO; 53 | } 54 | 55 | if (offset + wsize > fsize) { 56 | rt = ext2fs_file_set_size2(efile, offset + wsize); 57 | if (rt) { 58 | debugf("extfs_file_set_size(efile, %lld); failed", offset + size); 59 | return -EIO; 60 | } 61 | } 62 | 63 | rt = ext2fs_file_flush(efile); 64 | if (rt != 0 && rt != EXT2_ET_BLOCK_ALLOC_FAIL) { 65 | debugf("ext2_file_flush(efile); failed"); 66 | return -EIO; 67 | } 68 | 69 | debugf("leave"); 70 | return wsize; 71 | } 72 | 73 | int op_write (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) 74 | { 75 | size_t rt; 76 | ext2_file_t efile = EXT2FS_FILE(fi->fh); 77 | ext2_filsys e2fs = current_ext2fs(); 78 | 79 | debugf("enter"); 80 | debugf("path = %s", path); 81 | 82 | efile = do_open(e2fs, path, O_WRONLY); 83 | rt = do_write(efile, buf, size, offset); 84 | do_release(efile); 85 | 86 | debugf("leave"); 87 | return rt; 88 | } 89 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | SUBDIRS = macosx 3 | -------------------------------------------------------------------------------- /tools/macosx/Description.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IFPkgDescriptionDescription 6 | Fuse-ext2 is a EXT2 Filesystem support for FUSE. 7 | 8 | Dependencies 9 | ------------ 10 | 11 | Fuse-ext2 requires at least Fuse version 2.6.0 12 | 13 | - Linux: 14 | Fuse from http://fuse.sourceforge.net/ 15 | 16 | - Mac OS: 17 | Mac Fuse from http://code.google.com/p/macfuse/ 18 | 19 | 20 | Build 21 | ----- 22 | 23 | - Linux: 24 | $ ./configure 25 | $ make 26 | $ sudo make install 27 | 28 | You can use checkinstall or some other equivalent tool to generate install 29 | package for your distribution. 30 | 31 | - Mac OS: 32 | Standart build: 33 | $ ./configure 34 | $ make 35 | $ sudo make install 36 | 37 | Universal build: 38 | $ CFLAGS="-arch i386 -arch ppc" ../configure --disable-dependency-tracking 39 | $ make 40 | $ sudo make install 41 | 42 | Generating package: 43 | $ make package 44 | 45 | Alper Akcan 46 | 47 | IFPkgDescriptionTitle 48 | Fuse Ext2 Support 49 | 50 | 51 | -------------------------------------------------------------------------------- /tools/macosx/Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleGetInfoString 6 | FUSEEXT2_VERSION_LITERAL, Fuse-Ext2 Project 7 | CFBundleShortVersionString 8 | FUSEEXT2_VERSION_LITERAL 9 | IFMajorVersion 10 | 0 11 | IFMinorVersion 12 | 1 13 | IFPkgFlagAllowBackRev 14 | 15 | IFPkgFlagAuthorizationAction 16 | AdminAuthorization 17 | IFPkgFlagBackgroundAlignment 18 | topleft 19 | IFPkgFlagBackgroundScaling 20 | none 21 | IFPkgFlagDefaultLocation 22 | / 23 | IFPkgFlagFollowLinks 24 | 25 | IFPkgFlagInstallFat 26 | 27 | IFPkgFlagInstalledSize 28 | 0 29 | IFPkgFlagIsRequired 30 | 31 | IFPkgFlagOverwritePermissions 32 | 33 | IFPkgFlagRelocatable 34 | 35 | 39 | IFPkgFlagRootVolumeOnly 40 | 41 | IFPkgFlagUpdateInstalledLanguages 42 | 43 | IFPkgFormatVersion 44 | 0.10000000149011612 45 | 46 | 47 | -------------------------------------------------------------------------------- /tools/macosx/Install_resources/.VolumeIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alperakcan/fuse-ext2/ae35afb9ab08d87c66c1e021df792b3a7c4308b0/tools/macosx/Install_resources/.VolumeIcon.icns -------------------------------------------------------------------------------- /tools/macosx/Install_resources/Authors.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540 2 | {\fonttbl\f0\fnil\fcharset0 Monaco;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww16860\viewh12020\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural 6 | 7 | \f0\fs22 \cf0 \ 8 | \pard\pardeftab720 9 | \cf0 Alper Akcan \ 10 | Renzo Davoli \ 11 | \ 12 | - Contributors (in name order)\ 13 | \ 14 | Sanchez Guido \ 15 | Sven Gustafsson \ 16 | Erik Larsson \ 17 | Dave Vasilevsky \ 18 | } -------------------------------------------------------------------------------- /tools/macosx/Install_resources/ChangeLog.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf250 2 | {\fonttbl\f0\fnil\fcharset0 Monaco;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww16860\viewh12020\viewkind0 5 | \deftab720 6 | \pard\pardeftab720\ql\qnatural 7 | 8 | \f0\fs22 \cf0 Thu 24 Dec 2009 14:40:10 EET\ 9 | - version 0.0.7\ 10 | \ 11 | Tue 03 Nov 2009 04:02:06 AM EEST\ 12 | - get device volume name in probe stage. now diskutil shows volume name\ 13 | on device bar, as a result device mount point is created as\ 14 | '/Volumes/$\{volume_name\}'.\ 15 | - supports mac osx 10.6 in compability mode.\ 16 | \ 17 | Fri 09 Oct 2009 12:53:02 AM EEST\ 18 | - fixed big file support (write > 4G)\ 19 | \ 20 | Tue 29 Sep 2009 05:25:08 AM EEST\ 21 | - improved probe time (mount time improved %50)\ 22 | - improved mount time for read-only mode\ 23 | - mount time reduced from ~8 secs to ~2 secs\ 24 | - added windows_fat_(16/32) partition type to probe types\ 25 | - added 0.0.6 md5sum to release.xml\ 26 | - added release-beta.xml, just like macfuse\ 27 | - linux fs type probe decreased from 50 to 3500\ 28 | - disabled apple double files\ 29 | \ 30 | Wed 23 Sep 2009 00:15:10 AM EEST\ 31 | - version 0.0.6\ 32 | - fixed big file support for size > 4Gb\ 33 | - prefpane supports uninstall/update\ 34 | \ 35 | Mon 07 Sep 2009 00:02:40 AM EEST\ 36 | - added fuse-ext2.1 man page written by Renzo\ 37 | \ 38 | Wed 02 Sep 2009 07:43:48 PM EEST\ 39 | - merge in renzo branch rev.140 including:\ 40 | - support of file truncate\ 41 | - support of concurrent file access\ 42 | - view-os compatibility (see wiki.virtualsquare.org, umfuse)\ 43 | \ 44 | Mon 22 Jun 2009 05:36:45 PM EEST\ 45 | - uninstall support for mac\ 46 | - initial updater for mac\ 47 | \ 48 | Thu 11 Jun 2009 10:55:23 PM EEST\ 49 | - set version information at compile time for info.plist\ 50 | - corrected mke2fs path information in make-pkg.sh\ 51 | \ 52 | Tue 09 Jun 2009 02:09:15 AM EEST\ 53 | - upgrade to e2fsprogs-1.41.6\ 54 | \ 55 | Mon 08 Jun 2009 12:47:59 AM EEST\ 56 | - added uuid lib\ 57 | \ 58 | Wed 3 Jun 2009 07:09:27 PM EEST\ 59 | - version 0.0.5\ 60 | - updated authors file\ 61 | - minor directory changes\ 62 | \ 63 | Tue 2 Jun 2009 05:04:49 PM EEST\ 64 | - big/little endian support for universal build\ 65 | \ 66 | Tue 2 Jun 2009 00:39:06 AM EEST\ 67 | - upgrade to e2fsprogs 1.41.5\ 68 | - added mke2fs for disk format\ 69 | - added format support to diskutil\ 70 | \ 71 | Wed 27 May 2009 03:11:38 AM EEST\ 72 | - 10.4 tiger build instructions added to README\ 73 | - added /usr/local/[lib,include] to fuse-ext2\ 74 | compile flags.\ 75 | \ 76 | Tue 19 May 2009 07:34:23 PM EEST\ 77 | - version 0.0.4\ 78 | - get etx2 label in probe stage\ 79 | - make labeling work for universal build, also\ 80 | \ 81 | Tue 21 Apr 2009 02:32:57 PM EEST\ 82 | - merge in Dave Vasilevsky's labels patch\ 83 | \ 84 | Sat 04 Apr 2009 02:28:34 AM EET\ 85 | - disable multithread\ 86 | - reduce wait time to 5 seconds\ 87 | \ 88 | Mon 09 Feb 2009 04:42:51 PM EET\ 89 | - mac osx file system bundle support\ 90 | - automount support\ 91 | - first 'real' stable (read only)\ 92 | } -------------------------------------------------------------------------------- /tools/macosx/Install_resources/English.lproj/InstallationCheck.strings: -------------------------------------------------------------------------------- 1 | ../InstallationCheck.strings -------------------------------------------------------------------------------- /tools/macosx/Install_resources/English.lproj/VolumeCheck.strings: -------------------------------------------------------------------------------- 1 | ../VolumeCheck.strings -------------------------------------------------------------------------------- /tools/macosx/Install_resources/InstallationCheck: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PACKAGE_PATH=$1 4 | # INSTALL_PATH=$2 <-- NOTE: This is always set to '/' 5 | # INSTALL_VOLUME=$3 <-- NOTE: This is always set to '/' 6 | # SYSTEM_ROOT=$4 <-- NOTE: This is always set to '/' 7 | 8 | VERSION_PATH="/System/Library/CoreServices/SystemVersion" 9 | if [ ! -f "/${VERSION_PATH}.plist" ] 10 | then 11 | # Doesn't appear to have OS X installed. 12 | exit 112 13 | fi 14 | 15 | VERSION=`/usr/bin/defaults read "$VOLUME/$VERSION_PATH" ProductVersion` 16 | if [ x"$VERSION" = x"" ] 17 | then 18 | # Unable to get OS X version. 19 | exit 113 20 | fi 21 | 22 | MAJOR=`echo "$VERSION" | /usr/bin/awk -F. '{ print $1 }'` 23 | MINOR=`echo "$VERSION" | /usr/bin/awk -F. '{ print $2 }'` 24 | if [ \( x"$MAJOR" = x"" \) -o \( x"$MINOR" = x"" \) ] 25 | then 26 | # Unable to parse OS X version obtained from volume. 27 | exit 114 28 | fi 29 | 30 | if [ \( $MAJOR -lt 10 \) -o \( $MINOR -lt 4 \) ] 31 | then 32 | # Requires Mac OS X 10.4 or greater. 33 | exit 115 34 | fi 35 | 36 | # Success! 37 | exit 0 38 | -------------------------------------------------------------------------------- /tools/macosx/Install_resources/InstallationCheck.strings: -------------------------------------------------------------------------------- 1 | "16" = "Root does not appear to have Mac OS X installed."; 2 | "17" = "Unable to obtain Mac OS X version."; 3 | "18" = "Unable to parse OS X version obtained."; 4 | "19" = "Can only install on Mac OS X version 10.4 and above."; 5 | -------------------------------------------------------------------------------- /tools/macosx/Install_resources/README.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540 2 | {\fonttbl\f0\fnil\fcharset0 Monaco;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww15040\viewh9400\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural 6 | 7 | \f0\fs22 \cf0 \ 8 | \pard\pardeftab720 9 | \cf0 Fuse-ext2 is a EXT2 Filesystem support for FUSE.\ 10 | \ 11 | This software is based on both ntfs-3g, and ext2fuse packages.\ 12 | \ 13 | \ 14 | Dependencies\ 15 | ------------\ 16 | \ 17 | Fuse-ext2 requires at least Fuse version 2.6.0\ 18 | \ 19 | - Linux:\ 20 | Fuse from http://fuse.sourceforge.net/\ 21 | \ 22 | - Mac OS:\ 23 | Mac Fuse from http://code.google.com/p/macfuse/\ 24 | \ 25 | \ 26 | Build\ 27 | ----- \ 28 | \ 29 | - Linux:\ 30 | $ ./autogen.sh\ 31 | $ ./configure\ 32 | $ make\ 33 | $ sudo make install\ 34 | \ 35 | You can use checkinstall or some other equivalent tool to generate install\ 36 | package for your distribution.\ 37 | \ 38 | - Mac OS:\ 39 | Standart build:\ 40 | $ ./autogen.sh\ 41 | $ ./configure\ 42 | $ make\ 43 | $ sudo make install\ 44 | \ 45 | Universal build:\ 46 | $ ./autogen.sh\ 47 | $ CFLAGS="-arch i386 -arch ppc" ./configure --disable-dependency-tracking\ 48 | $ make\ 49 | $ sudo make install\ 50 | \ 51 | Tiger (Universal) build:\ 52 | $ export MACOSX_DEPLOYMENT_TARGET="10.4"\ 53 | $ export OSX_SDK="/Developer/SDKs/MacOSX10.4u.sdk"\ 54 | $ export OSX_CFLAGS="-isysroot $OSX_SDK -arch ppc -arch i386"\ 55 | $ export OSX_LDFLAGS="-Wl,-syslibroot,$OSX_SDK -arch ppc -arch i386"\ 56 | $ ./autogen.sh\ 57 | $ CFLAGS="$OSX_CFLAGS" CXXFLAGS="$OSX_CFLAGS" LDFLAGS="$OSX_LDFLAGS" ./configure --disable-dependency-tracking\ 58 | $ make\ 59 | $ sudo make install\ 60 | \ 61 | Generating package:\ 62 | $ make package\ 63 | \ 64 | Usage\ 65 | -----\ 66 | \ 67 | Usage: fuse-ext2 [-o option[,...]]\ 68 | \ 69 | Options: ro, force, allow_other\ 70 | Please see details in the manual.\ 71 | \ 72 | Example: fuse-ext2 /dev/sda1 /mnt/sda1\ 73 | \ 74 | Bugs\ 75 | ----\ 76 | \ 77 | there are no known bugs for read-only mode, read only mode should be ok for every one.\ 78 | \ 79 | altough, write support is available (and it is pretty stable) please do not mount your\ 80 | filesystems with write support unless you do not have anything to loose.\ 81 | \ 82 | please send output the output of below command while reporting bugs.\ 83 | \ 84 | $ /usr/local/bin/fuse-ext2 -v /dev/path /mnt/point -o debug\ 85 | \ 86 | Labels\ 87 | ------\ 88 | \ 89 | please do not use comma ',' in partition labels.\ 90 | \ 91 | wrong: e2label /dev/disk0s3 "linux,ext3"\ 92 | \ 93 | correct: e2label /dev/disk0s3 "linux-ext3"\ 94 | \ 95 | Contact\ 96 | -------\ 97 | \ 98 | Alper Akcan \ 99 | } 100 | -------------------------------------------------------------------------------- /tools/macosx/Install_resources/VolumeCheck: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # See http://developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution4/Concepts/sd_volume_check_ref.html 4 | 5 | VOLUME=$1 6 | 7 | VERSION_PATH="/System/Library/CoreServices/SystemVersion" 8 | 9 | if [ ! -f "${VOLUME}/${VERSION_PATH}.plist" ] 10 | then 11 | # Volume doesn't appear to have OS X installed. 12 | exit 112 13 | fi 14 | 15 | VERSION=`/usr/bin/defaults read "$VOLUME/$VERSION_PATH" ProductVersion` 16 | if [ x"$VERSION" = x"" ] 17 | then 18 | # Unable to get OS X version from volume. 19 | exit 113 20 | fi 21 | 22 | MAJOR=`echo "$VERSION" | /usr/bin/awk -F. '{ print $1 }'` 23 | MINOR=`echo "$VERSION" | /usr/bin/awk -F. '{ print $2 }'` 24 | if [ \( x"$MAJOR" = x"" \) -o \( x"$MINOR" = x"" \) ] 25 | then 26 | # Unable to parse OS X version obtained from volume. 27 | exit 114 28 | fi 29 | 30 | if [ \( $MAJOR -lt 10 \) -o \( $MINOR -lt 4 \) ] 31 | then 32 | # Requires Mac OS X 10.5 or greater. 33 | exit 115 34 | fi 35 | 36 | # Success! 37 | exit 0 38 | -------------------------------------------------------------------------------- /tools/macosx/Install_resources/VolumeCheck.strings: -------------------------------------------------------------------------------- 1 | "16" = "Volume does not appear to have Mac OS X installed."; 2 | "17" = "Unable to obtain Mac OS X version from Volume."; 3 | "18" = "Unable to parse OS X version obtained from volume."; 4 | "19" = "Can only install on a volume with Mac OS X version 10.4 and above."; 5 | -------------------------------------------------------------------------------- /tools/macosx/Install_resources/Welcome.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540 2 | {\fonttbl\f0\fnil\fcharset0 Monaco;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \margl1440\margr1440\vieww9000\viewh8400\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural 6 | 7 | \f0\fs22 \cf0 \ 8 | \pard\pardeftab720 9 | \cf0 Fuse-ext2 is a EXT2 Filesystem support for FUSE.\ 10 | \ 11 | This software is based on both ntfs-3g, and ext2fuse packages.\ 12 | \ 13 | \ 14 | Dependencies\ 15 | ------------\ 16 | \ 17 | Fuse-ext2 requires at least Fuse version 2.6.0\ 18 | \ 19 | - Linux:\ 20 | Fuse from http://fuse.sourceforge.net/\ 21 | \ 22 | - Mac OS:\ 23 | Mac Fuse from http://code.google.com/p/macfuse/\ 24 | \ 25 | \ 26 | Build\ 27 | ----- \ 28 | \ 29 | - Linux:\ 30 | $ ./autogen.sh\ 31 | $ ./configure\ 32 | $ make\ 33 | $ sudo make install\ 34 | \ 35 | You can use checkinstall or some other equivalent tool to generate install\ 36 | package for your distribution.\ 37 | \ 38 | - Mac OS:\ 39 | Standart build:\ 40 | $ ./autogen.sh\ 41 | $ ./configure\ 42 | $ make\ 43 | $ sudo make install\ 44 | \ 45 | Universal build:\ 46 | $ ./autogen.sh\ 47 | $ CFLAGS="-arch i386 -arch ppc" ./configure --disable-dependency-tracking\ 48 | $ make\ 49 | $ sudo make install\ 50 | \ 51 | Tiger (Universal) build:\ 52 | $ export MACOSX_DEPLOYMENT_TARGET="10.4"\ 53 | $ export OSX_SDK="/Developer/SDKs/MacOSX10.4u.sdk"\ 54 | $ export OSX_CFLAGS="-isysroot $OSX_SDK -arch ppc -arch i386"\ 55 | $ export OSX_LDFLAGS="-Wl,-syslibroot,$OSX_SDK -arch ppc -arch i386"\ 56 | $ ./autogen.sh\ 57 | $ CFLAGS="$OSX_CFLAGS" CXXFLAGS="$OSX_CFLAGS" LDFLAGS="$OSX_LDFLAGS" ./configure --disable-dependency-tracking\ 58 | $ make\ 59 | $ sudo make install\ 60 | \ 61 | Generating package:\ 62 | $ make package\ 63 | \ 64 | Usage\ 65 | -----\ 66 | \ 67 | Usage: fuse-ext2 [-o option[,...]]\ 68 | \ 69 | Options: ro, force, allow_other\ 70 | Please see details in the manual.\ 71 | \ 72 | Example: fuse-ext2 /dev/sda1 /mnt/sda1\ 73 | \ 74 | Bugs\ 75 | ----\ 76 | \ 77 | there are no known bugs for read-only mode, read only mode should be ok for every one.\ 78 | \ 79 | altough, write support is available (and it is pretty stable) please do not mount your\ 80 | filesystems with write support unless you do not have anything to loose.\ 81 | \ 82 | please send output the output of below command while reporting bugs.\ 83 | \ 84 | $ /usr/local/bin/fuse-ext2 -v /dev/path /mnt/point -o debug\ 85 | \ 86 | Labels\ 87 | ------\ 88 | \ 89 | please do not use comma ',' in partition labels.\ 90 | \ 91 | wrong: e2label /dev/disk0s3 "linux,ext3"\ 92 | \ 93 | correct: e2label /dev/disk0s3 "linux-ext3"\ 94 | \ 95 | Contact\ 96 | -------\ 97 | \ 98 | Alper Akcan \ 99 | } 100 | -------------------------------------------------------------------------------- /tools/macosx/Install_resources/background.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alperakcan/fuse-ext2/ae35afb9ab08d87c66c1e021df792b3a7c4308b0/tools/macosx/Install_resources/background.tiff -------------------------------------------------------------------------------- /tools/macosx/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | if DARWIN 3 | 4 | all: prefpane 5 | 6 | .PHONY: prefpane 7 | prefpane: 8 | ( cd $(top_srcdir)/tools/macosx/prefpane; \ 9 | xcodebuild; \ 10 | ) 11 | 12 | clean-local: 13 | ( cd $(top_srcdir)/tools/macosx/prefpane; \ 14 | xcodebuild clean; \ 15 | ) 16 | 17 | install-exec-local: 18 | $(INSTALL) -d $(DESTDIR)/Library/Filesystems/fuse-ext2.fs 19 | $(INSTALL) -d $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Support 20 | $(INSTALL) -d $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Contents 21 | $(INSTALL) -d $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Contents/Resources 22 | $(INSTALL) -d $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Contents/Resources/English.lproj 23 | $(INSTALL) -m 755 $(top_srcdir)/tools/macosx/fuse-ext2.fs/fuse-ext2.util $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/fuse-ext2.util 24 | $(INSTALL) -m 755 $(top_srcdir)/tools/macosx/fuse-ext2.fs/Contents/Resources/mount_fuse-ext2 $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Contents/Resources/mount_fuse-ext2 25 | sed "s/FUSEEXT2_VERSION_LITERAL/$(VERSION)/g" < $(top_srcdir)/tools/macosx/fuse-ext2.fs/Contents/Info.plist.in > $(top_srcdir)/tools/macosx/fuse-ext2.fs/Contents/Info.plist 26 | $(INSTALL) -m 644 $(top_srcdir)/tools/macosx/fuse-ext2.fs/Contents/Info.plist $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Contents/Info.plist 27 | $(INSTALL) -m 644 $(top_srcdir)/tools/macosx/fuse-ext2.fs/Contents/PkgInfo $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Contents/PkgInfo 28 | $(INSTALL) -m 644 $(top_srcdir)/tools/macosx/fuse-ext2.fs/Contents/Resources/English.lproj/InfoPlist.strings $(DESTDIR)/Library/Filesystems/fuse-ext2.fs/Contents/Resources/English.lproj/InfoPlist.strings 29 | $(INSTALL) -d $(DESTDIR)/Library/PreferencePanes 30 | cp -R $(top_srcdir)/tools/macosx/prefpane/build/Release/fuse-ext2.prefPane $(DESTDIR)/Library/PreferencePanes/fuse-ext2.prefPane 31 | 32 | endif 33 | -------------------------------------------------------------------------------- /tools/macosx/fuse-ext2.fs/Contents/Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | org.alperakcan.filesystems.fuse-ext2 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | fuse-ext2 13 | CFBundlePackageType 14 | fs 15 | CFBundleShortVersionString 16 | FUSEEXT2_VERSION_LITERAL 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | FUSEEXT2_VERSION_LITERAL 21 | FSMediaTypes 22 | 23 | Linux 24 | 25 | FSMediaProperties 26 | 27 | Content Hint 28 | Linux 29 | Leaf 30 | 31 | 32 | FSProbeArguments 33 | -p 34 | FSProbeExecutable 35 | ../../fuse-ext2.util 36 | FSProbeOrder 37 | 3500 38 | 39 | EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 40 | 41 | FSMediaProperties 42 | 43 | Content Hint 44 | EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 45 | Leaf 46 | 47 | 48 | FSProbeArguments 49 | -p 50 | FSProbeExecutable 51 | ../../fuse-ext2.util 52 | FSProbeOrder 53 | 3500 54 | 55 | Apple_UNIX_SVR2 56 | 57 | FSMediaProperties 58 | 59 | Content Hint 60 | Apple_UNIX_SVR2 61 | Leaf 62 | 63 | 64 | FSProbeArguments 65 | -p 66 | FSProbeExecutable 67 | ../../fuse-ext2.util 68 | FSProbeOrder 69 | 3500 70 | 71 | DOS_FAT_32 72 | 73 | FSMediaProperties 74 | 75 | Content Hint 76 | DOS_FAT_32 77 | Leaf 78 | 79 | 80 | FSProbeArguments 81 | -p 82 | FSProbeExecutable 83 | ../../fuse-ext2.util 84 | FSProbeOrder 85 | 3500 86 | 87 | DOS_FAT_16 88 | 89 | FSMediaProperties 90 | 91 | Content Hint 92 | DOS_FAT_16 93 | Leaf 94 | 95 | 96 | FSProbeArguments 97 | -p 98 | FSProbeExecutable 99 | ../../fuse-ext2.util 100 | FSProbeOrder 101 | 3500 102 | 103 | Windows_FAT_32 104 | 105 | FSMediaProperties 106 | 107 | Content Hint 108 | Windows_FAT_32 109 | Leaf 110 | 111 | 112 | FSProbeArguments 113 | -p 114 | FSProbeExecutable 115 | ../../fuse-ext2.util 116 | FSProbeOrder 117 | 3500 118 | 119 | Windows_FAT_16 120 | 121 | FSMediaProperties 122 | 123 | Content Hint 124 | Windows_FAT_16 125 | Leaf 126 | 127 | 128 | FSProbeArguments 129 | -p 130 | FSProbeExecutable 131 | ../../fuse-ext2.util 132 | FSProbeOrder 133 | 3500 134 | 135 | Whole 136 | 137 | FSMediaProperties 138 | 139 | Leaf 140 | 141 | Whole 142 | 143 | 144 | FSProbeArguments 145 | -p 146 | FSProbeExecutable 147 | ../../fuse-ext2.util 148 | FSProbeOrder 149 | 4900 150 | 151 | GPT_Linux_filesystem 152 | 153 | FSMediaProperties 154 | 155 | Content Hint 156 | 0FC63DAF-8483-4772-8E79-3D69D8477DE4 157 | Leaf 158 | 159 | 160 | FSProbeArguments 161 | -p 162 | FSProbeExecutable 163 | ../../fuse-ext2.util 164 | FSProbeOrder 165 | 3500 166 | 167 | 168 | FSPersonalities 169 | 170 | fuse-ext2 171 | 172 | FSFormatContentMask 173 | Linux 174 | FSName 175 | fuse-ext2 176 | FSSubType 177 | 11 178 | FSFormatMinimumSize 179 | 0 180 | FSFormatMaximumSize 181 | 0 182 | FSFormatArguments 183 | -f 184 | FSFormatExecutable 185 | ../../fuse-ext2.util 186 | FSMountArguments 187 | -m 188 | FSMountExecutable 189 | ../../fuse-ext2.util 190 | FSRepairArguments 191 | -y 192 | FSRepairExecutable 193 | ../../fuse-ext2.util 194 | FSVerificationArguments 195 | -v 196 | FSVerificationExecutable 197 | ../../fuse-ext2.util 198 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /tools/macosx/fuse-ext2.fs/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | fs ???? -------------------------------------------------------------------------------- /tools/macosx/fuse-ext2.fs/Contents/Resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | fuse-ext2 7 | FSPersonalities 8 | 9 | fuse-ext2 10 | 11 | FSName 12 | fuse-ext2 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tools/macosx/fuse-ext2.fs/Contents/Resources/mount_fuse-ext2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | "/Library/Filesystems/fuse-ext2.fs/fuse-ext2.util" "-m" "$@" 4 | -------------------------------------------------------------------------------- /tools/macosx/make-pkg.sh: -------------------------------------------------------------------------------- 1 | # 2 | # This script is heavly based on ntfs-3g mac osx package, 3 | # thanks to Erik Larsson, and Paul Marks for their efforts. 4 | # 5 | 6 | #!/bin/sh 7 | 8 | # Exit immediately in case of error 9 | set -e 10 | 11 | SUDO="sudo" 12 | SED_E="${SUDO} sed -e" 13 | MV="${SUDO} mv" 14 | CP_R="${SUDO} cp -R" 15 | RM_RF="${SUDO} rm -rf" 16 | MKDIR_P="${SUDO} mkdir -p" 17 | LN_SF="${SUDO} ln -sf" 18 | INSTALL_C="${SUDO} install -c" 19 | CHOWN_R="${SUDO} chown -R" 20 | PKGBUILD="${SUDO} pkgbuild" 21 | TMP_FOLDER="$(mktemp -d)" 22 | DISTRIBUTION_FOLDER="$TMP_FOLDER/Distribution_Folder" 23 | SETFILE="${SUDO} $(xcode-select -p)/Tools/SetFile" 24 | 25 | FUSEEXT2_NAME="fuse-ext2" 26 | 27 | FUSEEXT2_VERSION="$1" 28 | BUILD_FOLDER="$2" 29 | MKPKG_FOLDER="$3" 30 | 31 | if [ x"$FUSEEXT2_VERSION" = x"" ] 32 | then 33 | echo "Usage: make-pkg.sh " 34 | exit 1 35 | fi 36 | 37 | if [ x"$BUILD_FOLDER" = x"" ] 38 | then 39 | echo "Usage: make-pkg.sh " 40 | exit 1 41 | fi 42 | 43 | if [ x"$MKPKG_FOLDER" = x"" ] 44 | then 45 | echo "Usage: make-pkg.sh " 46 | exit 1 47 | fi 48 | 49 | make -f "$BUILD_FOLDER/Makefile" DESTDIR="$DISTRIBUTION_FOLDER" install 50 | ${CHOWN_R} root:wheel ${TMP_FOLDER} 51 | 52 | ${PKGBUILD} --identifier ${FUSEEXT2_NAME} \ 53 | --root "$DISTRIBUTION_FOLDER" \ 54 | --version $FUSEEXT2_VERSION \ 55 | ${FUSEEXT2_NAME}.pkg 56 | 57 | ${CHOWN_R} root:admin ${FUSEEXT2_NAME}.pkg 58 | 59 | sudo hdiutil create -layout NONE -megabytes 1 -fs HFS+ -volname "${FUSEEXT2_NAME}-${FUSEEXT2_VERSION}" "${TMP_FOLDER}/${FUSEEXT2_NAME}-${FUSEEXT2_VERSION}.dmg" 60 | sudo hdiutil attach -private -nobrowse "${TMP_FOLDER}/${FUSEEXT2_NAME}-${FUSEEXT2_VERSION}.dmg" 61 | 62 | VOLUME_PATH="/Volumes/${FUSEEXT2_NAME}-${FUSEEXT2_VERSION}" 63 | sudo cp -pRX ${FUSEEXT2_NAME}.pkg "$VOLUME_PATH" 64 | 65 | # Set the custom icon. 66 | sudo cp -pRX "${MKPKG_FOLDER}/Install_resources/.VolumeIcon.icns" "${VOLUME_PATH}/.VolumeIcon.icns" 67 | ${SETFILE} -a C "$VOLUME_PATH" 68 | 69 | # Copy over the license file. 70 | sudo cp "${MKPKG_FOLDER}/Install_resources/README.rtf" "${VOLUME_PATH}/README.rtf" 71 | sudo cp "${MKPKG_FOLDER}/Install_resources/Authors.rtf" "${VOLUME_PATH}/Authors.rtf" 72 | sudo cp "${MKPKG_FOLDER}/Install_resources/ChangeLog.rtf" "${VOLUME_PATH}/ChangeLog.rtf" 73 | sudo cp "${MKPKG_FOLDER}/Install_resources/License.rtf" "${VOLUME_PATH}/License.rtf" 74 | 75 | # Detach the volume. 76 | hdiutil detach "$VOLUME_PATH" 77 | 78 | # Convert to a read-only compressed dmg. 79 | sudo hdiutil convert -imagekey zlib-level=9 -format UDZO "${TMP_FOLDER}/${FUSEEXT2_NAME}-${FUSEEXT2_VERSION}.dmg" -o "${FUSEEXT2_NAME}-${FUSEEXT2_VERSION}.dmg" 80 | 81 | ${RM_RF} ${TMP_FOLDER} ${FUSEEXT2_NAME}.pkg 82 | 83 | echo "SUCCESS: All Done." 84 | exit 0 85 | -------------------------------------------------------------------------------- /tools/macosx/prefpane/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alperakcan/fuse-ext2/ae35afb9ab08d87c66c1e021df792b3a7c4308b0/tools/macosx/prefpane/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /tools/macosx/prefpane/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | org.alperakcan.prefpane.${PRODUCT_NAME:identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | NSMainNibFile 26 | fuse_ext2Pref 27 | NSPrefPaneIconFile 28 | penguin.png 29 | NSPrefPaneIconLabel 30 | fuse-ext2 31 | NSPrincipalClass 32 | fuse_ext2Pref 33 | 34 | 35 | -------------------------------------------------------------------------------- /tools/macosx/prefpane/fuse-ext2.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 551ADFB30FA6412600AA0ADB /* penguin.png in Resources */ = {isa = PBXBuildFile; fileRef = 551ADFB20FA6412600AA0ADB /* penguin.png */; }; 11 | 55CE1E780FE3270F00CCDD5A /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55CE1E770FE3270F00CCDD5A /* Security.framework */; }; 12 | 8D202CEA0486D31800D8A456 /* fuse-ext2_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 32DBCFA20370C41700C91783 /* fuse-ext2_Prefix.pch */; }; 13 | 8D202CEB0486D31800D8A456 /* fuse_ext2Pref.h in Headers */ = {isa = PBXBuildFile; fileRef = F506C03C013D9D7901CA16C8 /* fuse_ext2Pref.h */; }; 14 | 8D202CED0486D31800D8A456 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; }; 15 | 8D202CEF0486D31800D8A456 /* fuse_ext2Pref.xib in Resources */ = {isa = PBXBuildFile; fileRef = F506C042013D9D8C01CA16C8 /* fuse_ext2Pref.xib */; }; 16 | 8D202CF10486D31800D8A456 /* fuse_ext2Pref.m in Sources */ = {isa = PBXBuildFile; fileRef = F506C03D013D9D7901CA16C8 /* fuse_ext2Pref.m */; }; 17 | 8D202CF30486D31800D8A456 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; }; 18 | 8D202CF40486D31800D8A456 /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F506C035013D953901CA16C8 /* PreferencePanes.framework */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 23 | 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 24 | 089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 25 | 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 26 | 32DBCFA20370C41700C91783 /* fuse-ext2_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "fuse-ext2_Prefix.pch"; sourceTree = ""; }; 27 | 551ADFB20FA6412600AA0ADB /* penguin.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = penguin.png; sourceTree = ""; }; 28 | 55CE1E770FE3270F00CCDD5A /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; 29 | 8D202CF70486D31800D8A456 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 30 | 8D202CF80486D31800D8A456 /* fuse-ext2.prefPane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "fuse-ext2.prefPane"; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | F506C035013D953901CA16C8 /* PreferencePanes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PreferencePanes.framework; path = /System/Library/Frameworks/PreferencePanes.framework; sourceTree = ""; }; 32 | F506C03C013D9D7901CA16C8 /* fuse_ext2Pref.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.h; path = fuse_ext2Pref.h; sourceTree = ""; tabWidth = 8; }; 33 | F506C03D013D9D7901CA16C8 /* fuse_ext2Pref.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 8; lastKnownFileType = sourcecode.c.objc; path = fuse_ext2Pref.m; sourceTree = ""; tabWidth = 8; }; 34 | F506C043013D9D8C01CA16C8 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/fuse_ext2Pref.xib; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 8D202CF20486D31800D8A456 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | 8D202CF30486D31800D8A456 /* Cocoa.framework in Frameworks */, 43 | 8D202CF40486D31800D8A456 /* PreferencePanes.framework in Frameworks */, 44 | 55CE1E780FE3270F00CCDD5A /* Security.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 089C166AFE841209C02AAC07 /* fuse-ext2 */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 08FB77AFFE84173DC02AAC07 /* Classes */, 55 | 32DBCFA10370C40200C91783 /* Other Sources */, 56 | 089C167CFE841241C02AAC07 /* Resources */, 57 | 089C1671FE841209C02AAC07 /* Frameworks and Libraries */, 58 | 19C28FB8FE9D52D311CA2CBB /* Products */, 59 | ); 60 | name = "fuse-ext2"; 61 | sourceTree = ""; 62 | }; 63 | 089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 55CE1E770FE3270F00CCDD5A /* Security.framework */, 67 | 1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */, 68 | 1058C7AEFEA557BF11CA2CBB /* Other Frameworks */, 69 | ); 70 | name = "Frameworks and Libraries"; 71 | sourceTree = ""; 72 | }; 73 | 089C167CFE841241C02AAC07 /* Resources */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 551ADFB20FA6412600AA0ADB /* penguin.png */, 77 | 8D202CF70486D31800D8A456 /* Info.plist */, 78 | 089C167DFE841241C02AAC07 /* InfoPlist.strings */, 79 | F506C042013D9D8C01CA16C8 /* fuse_ext2Pref.xib */, 80 | ); 81 | name = Resources; 82 | sourceTree = ""; 83 | }; 84 | 08FB77AFFE84173DC02AAC07 /* Classes */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | F506C03C013D9D7901CA16C8 /* fuse_ext2Pref.h */, 88 | F506C03D013D9D7901CA16C8 /* fuse_ext2Pref.m */, 89 | ); 90 | name = Classes; 91 | sourceTree = ""; 92 | }; 93 | 1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */, 97 | F506C035013D953901CA16C8 /* PreferencePanes.framework */, 98 | ); 99 | name = "Linked Frameworks"; 100 | sourceTree = ""; 101 | }; 102 | 1058C7AEFEA557BF11CA2CBB /* Other Frameworks */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 089C1672FE841209C02AAC07 /* Foundation.framework */, 106 | 089C167FFE841241C02AAC07 /* AppKit.framework */, 107 | ); 108 | name = "Other Frameworks"; 109 | sourceTree = ""; 110 | }; 111 | 19C28FB8FE9D52D311CA2CBB /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 8D202CF80486D31800D8A456 /* fuse-ext2.prefPane */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | 32DBCFA10370C40200C91783 /* Other Sources */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 32DBCFA20370C41700C91783 /* fuse-ext2_Prefix.pch */, 123 | ); 124 | name = "Other Sources"; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXHeadersBuildPhase section */ 130 | 8D202CE90486D31800D8A456 /* Headers */ = { 131 | isa = PBXHeadersBuildPhase; 132 | buildActionMask = 2147483647; 133 | files = ( 134 | 8D202CEA0486D31800D8A456 /* fuse-ext2_Prefix.pch in Headers */, 135 | 8D202CEB0486D31800D8A456 /* fuse_ext2Pref.h in Headers */, 136 | ); 137 | runOnlyForDeploymentPostprocessing = 0; 138 | }; 139 | /* End PBXHeadersBuildPhase section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | 8D202CE80486D31800D8A456 /* fuse-ext2 */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 1DBD214808BA80EA00186707 /* Build configuration list for PBXNativeTarget "fuse-ext2" */; 145 | buildPhases = ( 146 | 8D202CE90486D31800D8A456 /* Headers */, 147 | 8D202CEC0486D31800D8A456 /* Resources */, 148 | 8D202CF00486D31800D8A456 /* Sources */, 149 | 8D202CF20486D31800D8A456 /* Frameworks */, 150 | 8D202CF50486D31800D8A456 /* Rez */, 151 | ); 152 | buildRules = ( 153 | ); 154 | dependencies = ( 155 | ); 156 | name = "fuse-ext2"; 157 | productInstallPath = "$(HOME)/Library/PreferencePanes"; 158 | productName = "fuse-ext2"; 159 | productReference = 8D202CF80486D31800D8A456 /* fuse-ext2.prefPane */; 160 | productType = "com.apple.product-type.bundle"; 161 | }; 162 | /* End PBXNativeTarget section */ 163 | 164 | /* Begin PBXProject section */ 165 | 089C1669FE841209C02AAC07 /* Project object */ = { 166 | isa = PBXProject; 167 | attributes = { 168 | }; 169 | buildConfigurationList = 1DBD214C08BA80EA00186707 /* Build configuration list for PBXProject "fuse-ext2" */; 170 | compatibilityVersion = "Xcode 3.1"; 171 | developmentRegion = English; 172 | hasScannedForEncodings = 1; 173 | knownRegions = ( 174 | en, 175 | ); 176 | mainGroup = 089C166AFE841209C02AAC07 /* fuse-ext2 */; 177 | projectDirPath = ""; 178 | projectRoot = ""; 179 | targets = ( 180 | 8D202CE80486D31800D8A456 /* fuse-ext2 */, 181 | ); 182 | }; 183 | /* End PBXProject section */ 184 | 185 | /* Begin PBXResourcesBuildPhase section */ 186 | 8D202CEC0486D31800D8A456 /* Resources */ = { 187 | isa = PBXResourcesBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | 8D202CED0486D31800D8A456 /* InfoPlist.strings in Resources */, 191 | 8D202CEF0486D31800D8A456 /* fuse_ext2Pref.xib in Resources */, 192 | 551ADFB30FA6412600AA0ADB /* penguin.png in Resources */, 193 | ); 194 | runOnlyForDeploymentPostprocessing = 0; 195 | }; 196 | /* End PBXResourcesBuildPhase section */ 197 | 198 | /* Begin PBXRezBuildPhase section */ 199 | 8D202CF50486D31800D8A456 /* Rez */ = { 200 | isa = PBXRezBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | }; 206 | /* End PBXRezBuildPhase section */ 207 | 208 | /* Begin PBXSourcesBuildPhase section */ 209 | 8D202CF00486D31800D8A456 /* Sources */ = { 210 | isa = PBXSourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | 8D202CF10486D31800D8A456 /* fuse_ext2Pref.m in Sources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXSourcesBuildPhase section */ 218 | 219 | /* Begin PBXVariantGroup section */ 220 | 089C167DFE841241C02AAC07 /* InfoPlist.strings */ = { 221 | isa = PBXVariantGroup; 222 | children = ( 223 | 089C167EFE841241C02AAC07 /* English */, 224 | ); 225 | name = InfoPlist.strings; 226 | sourceTree = ""; 227 | }; 228 | F506C042013D9D8C01CA16C8 /* fuse_ext2Pref.xib */ = { 229 | isa = PBXVariantGroup; 230 | children = ( 231 | F506C043013D9D8C01CA16C8 /* English */, 232 | ); 233 | name = fuse_ext2Pref.xib; 234 | sourceTree = ""; 235 | }; 236 | /* End PBXVariantGroup section */ 237 | 238 | /* Begin XCBuildConfiguration section */ 239 | 1DBD214908BA80EA00186707 /* Debug */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 243 | COPY_PHASE_STRIP = NO; 244 | GCC_DYNAMIC_NO_PIC = NO; 245 | GCC_ENABLE_FIX_AND_CONTINUE = YES; 246 | GCC_MODEL_TUNING = G5; 247 | GCC_OPTIMIZATION_LEVEL = 0; 248 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 249 | GCC_PREFIX_HEADER = "fuse-ext2_Prefix.pch"; 250 | GCC_VERSION = ""; 251 | INFOPLIST_FILE = Info.plist; 252 | INSTALL_PATH = "$(HOME)/Library/PreferencePanes"; 253 | PRODUCT_NAME = "fuse-ext2"; 254 | SDKROOT = macosx; 255 | VALID_ARCHS = x86_64; 256 | WRAPPER_EXTENSION = prefPane; 257 | ZERO_LINK = YES; 258 | }; 259 | name = Debug; 260 | }; 261 | 1DBD214A08BA80EA00186707 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 265 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 266 | GCC_MODEL_TUNING = G5; 267 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 268 | GCC_PREFIX_HEADER = "fuse-ext2_Prefix.pch"; 269 | GCC_VERSION = ""; 270 | INFOPLIST_FILE = Info.plist; 271 | INSTALL_PATH = "$(HOME)/Library/PreferencePanes"; 272 | PRODUCT_NAME = "fuse-ext2"; 273 | SDKROOT = macosx; 274 | VALID_ARCHS = x86_64; 275 | WRAPPER_EXTENSION = prefPane; 276 | }; 277 | name = Release; 278 | }; 279 | 1DBD214D08BA80EA00186707 /* Debug */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 283 | GCC_C_LANGUAGE_STANDARD = c99; 284 | GCC_VERSION = 4.0; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 286 | GCC_WARN_UNUSED_VARIABLE = YES; 287 | ONLY_ACTIVE_ARCH = NO; 288 | PREBINDING = NO; 289 | SDKROOT = macosx10.4; 290 | }; 291 | name = Debug; 292 | }; 293 | 1DBD214E08BA80EA00186707 /* Release */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 297 | GCC_C_LANGUAGE_STANDARD = c99; 298 | GCC_VERSION = 4.0; 299 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | PREBINDING = NO; 302 | SDKROOT = macosx10.4; 303 | }; 304 | name = Release; 305 | }; 306 | /* End XCBuildConfiguration section */ 307 | 308 | /* Begin XCConfigurationList section */ 309 | 1DBD214808BA80EA00186707 /* Build configuration list for PBXNativeTarget "fuse-ext2" */ = { 310 | isa = XCConfigurationList; 311 | buildConfigurations = ( 312 | 1DBD214908BA80EA00186707 /* Debug */, 313 | 1DBD214A08BA80EA00186707 /* Release */, 314 | ); 315 | defaultConfigurationIsVisible = 0; 316 | defaultConfigurationName = Release; 317 | }; 318 | 1DBD214C08BA80EA00186707 /* Build configuration list for PBXProject "fuse-ext2" */ = { 319 | isa = XCConfigurationList; 320 | buildConfigurations = ( 321 | 1DBD214D08BA80EA00186707 /* Debug */, 322 | 1DBD214E08BA80EA00186707 /* Release */, 323 | ); 324 | defaultConfigurationIsVisible = 0; 325 | defaultConfigurationName = Release; 326 | }; 327 | /* End XCConfigurationList section */ 328 | }; 329 | rootObject = 089C1669FE841209C02AAC07 /* Project object */; 330 | } 331 | -------------------------------------------------------------------------------- /tools/macosx/prefpane/fuse-ext2_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'fuse-ext2' target in the 'fuse-ext2' project. 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /tools/macosx/prefpane/fuse_ext2Pref.h: -------------------------------------------------------------------------------- 1 | // 2 | // fuse_ext2Pref.h 3 | // fuse-ext2 4 | // 5 | // Created by Alper Akcan on 4/27/09. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | @interface fuse_ext2Pref : NSPreferencePane 12 | { 13 | @private 14 | IBOutlet NSTextField *aboutLabel; 15 | IBOutlet NSButton *removeButton; 16 | IBOutlet NSButton *updateButton; 17 | IBOutlet NSTextField *installedLabel; 18 | IBOutlet NSTextField *updateLabel; 19 | IBOutlet NSProgressIndicator *spinnerRemove; 20 | IBOutlet NSProgressIndicator *spinnerUpdate; 21 | AuthorizationRef authorizationReference; 22 | BOOL taskRunning; 23 | BOOL doUpdate; 24 | } 25 | 26 | - (void) mainViewDidLoad; 27 | - (IBAction) updateFuseExt2: (id) sender; 28 | - (IBAction) removeFuseExt2: (id) sender; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /tools/macosx/prefpane/fuse_ext2Pref.m: -------------------------------------------------------------------------------- 1 | // 2 | // fuse_ext2Pref.m 3 | // fuse-ext2 4 | // 5 | // Created by Alper Akcan on 4/27/09. 6 | // 7 | // Authorization related functions 8 | // authorize 9 | // copyRights 10 | // deauthorize 11 | // runTaskForPath 12 | // are heavly based on MacFUSE PrefPane implementation 13 | // 14 | 15 | #import "fuse_ext2Pref.h" 16 | 17 | #import 18 | 19 | static NSString *kreleasePath = @"http://fuse-ext2.svn.sourceforge.net/viewvc/fuse-ext2/release/release.xml"; 20 | static NSString *kinstallPath = @"/usr/local/bin/fuse-ext2.install"; 21 | static NSString *kuninstallPath = @"/usr/local/bin/fuse-ext2.uninstall"; 22 | static NSString *kinstalledPath = @"/Library/Filesystems/fuse-ext2.fs/Contents/Info.plist"; 23 | static NSString *kaboutLabelString = @"fuse-ext2 is a ext2/ext3/ext4 filesystem support for Fuse. Please visit fuse-ext2 webpage (https://github.com/alperakcan/fuse-ext2) for more information."; 24 | static NSString *kinstalledString = @"Installed Version:"; 25 | static NSString *kinstallingString = @"Installing new version."; 26 | static NSString *kcheckingString = @"Checking for new version."; 27 | static NSString *kavailableString = @"New version availeble:"; 28 | static NSString *kupdateString = @"No Updates Available At This Time."; 29 | static const NSTimeInterval kNetworkTimeOutInterval = 60.00; 30 | 31 | @interface fuse_ext2Pref (PrivateMethods) 32 | 33 | - (NSString *) availableVersion; 34 | - (NSString *) installedVersion; 35 | - (void) updateGUI; 36 | 37 | - (BOOL) authorize; 38 | - (BOOL) copyRights; 39 | - (void) deauthorize; 40 | 41 | - (BOOL) isTaskRunning; 42 | - (void) setTaskRunning: (BOOL) value; 43 | - (int) runTaskForPath:(NSString *) path withArguments:(NSArray *) arguments authorized:(BOOL) authorized output:(NSData **) output; 44 | 45 | @end 46 | 47 | @implementation fuse_ext2Pref 48 | 49 | - (BOOL) isTaskRunning 50 | { 51 | return taskRunning; 52 | } 53 | 54 | - (void) setTaskRunning: (BOOL) value 55 | { 56 | if (taskRunning != value) { 57 | taskRunning = value; 58 | } 59 | } 60 | 61 | - (int) runTaskForPath:(NSString *) path withArguments:(NSArray *) arguments authorized:(BOOL) authorized output:(NSData **) output 62 | { 63 | int result = 0; 64 | NSFileHandle *outFile = nil; 65 | [self setTaskRunning:YES]; 66 | if (authorized == NO) { 67 | // non-authorized 68 | NSTask* task = [[[NSTask alloc] init] autorelease]; 69 | [task setLaunchPath:path]; 70 | [task setArguments:arguments]; 71 | [task setEnvironment:[NSDictionary dictionary]]; 72 | NSPipe *outPipe = [NSPipe pipe]; 73 | [task setStandardOutput:outPipe]; 74 | 75 | @try { 76 | [task launch]; 77 | } @catch (NSException *err) { 78 | NSLog(@"fuse-ext2.PrefPane: caught exception %@ when launching task %@", err, task); 79 | [self setTaskRunning:NO]; 80 | return -1; 81 | } 82 | 83 | NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 84 | NSDate *startDate = [NSDate date]; 85 | do { 86 | NSDate *waitDate = [NSDate dateWithTimeIntervalSinceNow:0.01]; 87 | if ([waitDate timeIntervalSinceDate:startDate] > kNetworkTimeOutInterval) { 88 | result = -1; 89 | [task terminate]; 90 | } 91 | [runLoop runUntilDate:waitDate]; 92 | } while ([task isRunning]); 93 | 94 | if (result == 0) { 95 | result = [task terminationStatus]; 96 | } 97 | if (output) { 98 | outFile = [outPipe fileHandleForReading]; 99 | } 100 | } else { 101 | // authorized 102 | if ([self authorize] == NO) { 103 | return -1; 104 | } 105 | FILE *outPipe = NULL; 106 | unsigned int numArgs = [arguments count]; 107 | const char **args = malloc(sizeof(char*) * (numArgs + 1)); 108 | if (!args) { 109 | [self setTaskRunning:NO]; 110 | return -1; 111 | } 112 | const char *cPath = [path fileSystemRepresentation]; 113 | for (unsigned int i = 0; i < numArgs; i++) { 114 | args[i] = [[arguments objectAtIndex:i] fileSystemRepresentation]; 115 | } 116 | 117 | args[numArgs] = NULL; 118 | 119 | AuthorizationFlags myFlags = kAuthorizationFlagDefaults; 120 | result = AuthorizationExecuteWithPrivileges(authorizationReference, cPath, myFlags, (char * const *) args, &outPipe); 121 | free(args); 122 | if (result == 0) { 123 | int wait_status; 124 | int pid = 0; 125 | NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 126 | do { 127 | NSDate *waitDate = [NSDate dateWithTimeIntervalSinceNow:0.1]; 128 | [runLoop runUntilDate:waitDate]; 129 | pid = waitpid(-1, &wait_status, WNOHANG); 130 | } while (pid == 0); 131 | if (pid == -1 || !WIFEXITED(wait_status)) { 132 | result = -1; 133 | } else { 134 | result = WEXITSTATUS(wait_status); 135 | } 136 | if (output) { 137 | int fd = fileno(outPipe); 138 | outFile = [[[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES] autorelease]; 139 | } 140 | } 141 | } 142 | if (outFile && output) { 143 | *output = [outFile readDataToEndOfFile]; 144 | } 145 | [self setTaskRunning:NO]; 146 | return result; 147 | } 148 | 149 | - (IBAction) updateFuseExt2: (id) sender 150 | { 151 | int ret; 152 | NSData *output = nil; 153 | NSLog(@"fuse-ext2.PrefPane: update button clicked\n"); 154 | if (taskRunning == YES) { 155 | return; 156 | } 157 | [removeButton setEnabled:NO]; 158 | [updateButton setEnabled:NO]; 159 | if (doUpdate == NO) { 160 | [spinnerUpdate startAnimation:self]; 161 | [updateLabel setStringValue:kcheckingString]; 162 | [self updateGUI]; 163 | } else { 164 | [spinnerUpdate startAnimation:self]; 165 | [updateLabel setStringValue:kinstallingString]; 166 | ret = [self runTaskForPath:kinstallPath withArguments:[NSArray arrayWithObjects:@"-u", kreleasePath, @"-r", nil] authorized:YES output:&output]; 167 | if (ret != 0) { 168 | NSLog(@"fuse-ext2.PrefPane: fuse-ext2.install -u -r failed"); 169 | } 170 | if (output) { 171 | NSString *string = [[[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding] autorelease]; 172 | NSLog(@"fuse-ext2.PrefPane: output;\n'%@'\n", string); 173 | } 174 | [self updateGUI]; 175 | } 176 | } 177 | 178 | - (IBAction) removeFuseExt2: (id) sender 179 | { 180 | int ret; 181 | int authorized; 182 | NSData *output = nil; 183 | if (taskRunning == YES) { 184 | return; 185 | } 186 | [removeButton setEnabled:NO]; 187 | [updateButton setEnabled:NO]; 188 | [spinnerRemove startAnimation:self]; 189 | authorized = [self authorize]; 190 | if (authorized != YES) { 191 | [spinnerRemove stopAnimation:self]; 192 | [self updateGUI]; 193 | return; 194 | } 195 | [updateLabel setStringValue:@"Removing fuse-ext2..."]; 196 | NSLog(@"fuse-ext2.PrefPane: remove button clicked\n"); 197 | ret = [self runTaskForPath:kuninstallPath withArguments:[NSArray arrayWithObjects:@"-u", nil] authorized:YES output:&output]; 198 | NSLog(@"fuse-ext2.PrefPane: runtaskforpath returned:%d\n", ret); 199 | if (output) { 200 | NSString *string = [[[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding] autorelease]; 201 | NSLog(@"fuse-ext2.PrefPane: output;\n'%@'\n", string); 202 | } 203 | if (ret != 0) { 204 | [updateLabel setStringValue:@"Removing fuse-ext2 failed, check console log for details."]; 205 | } else { 206 | [updateLabel setStringValue:@"Removed fuse-ext2."]; 207 | } 208 | [spinnerRemove stopAnimation:self]; 209 | [self updateGUI]; 210 | } 211 | 212 | - (NSString *) availableVersion 213 | { 214 | int ret; 215 | NSData *output; 216 | NSString *string; 217 | NSString *versionString; 218 | NSString *versionTag; 219 | NSScanner *dataScanner; 220 | output = nil; 221 | versionTag = @"Available Version:"; 222 | ret = [self runTaskForPath:kinstallPath withArguments:[NSArray arrayWithObjects:@"-u", kreleasePath, @"-a", nil] authorized:NO output:&output]; 223 | if (ret != 0) { 224 | NSLog(@"fuse-ext2.PrefPane: fuse-ext2.install -u -a failed"); 225 | return nil; 226 | } 227 | if (output == nil) { 228 | NSLog(@"fuse-ext2.PrefPane: fuse-ext2.install -u -a failed"); 229 | return nil; 230 | } 231 | string = [[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding]; 232 | NSLog(@"fuse-ext2.PrefPane: output;\n'%@'", string); 233 | dataScanner = [[NSScanner alloc] initWithString:string]; 234 | if ([dataScanner scanString:versionTag intoString:&versionString]) { 235 | NSLog(@"fuse-ext2.PrefPane: versionString:%@", versionString); 236 | versionString = nil; 237 | if ([dataScanner scanUpToString:@"\n" intoString:&versionString]) { 238 | if (versionString == nil) { 239 | NSLog(@"fuse-ext2.PrefPane: version is nil"); 240 | } else { 241 | NSLog(@"fuse-ext2.PrefPane: version is not nil:%@", versionString); 242 | } 243 | return [[NSString alloc] initWithString: versionString]; 244 | } else { 245 | NSLog(@"fuse-ext2.PrefPane: scanuptostring failed"); 246 | } 247 | } else { 248 | NSLog(@"fuse-ext2.PrefPane: datascanner failed"); 249 | } 250 | [string release]; 251 | [dataScanner release]; 252 | return nil; 253 | } 254 | 255 | - (NSString *) installedVersion 256 | { 257 | NSString *fuse_ext2Path; 258 | NSString *versionString; 259 | NSString *bundleVersion; 260 | NSDictionary *fuse_ext2Plist; 261 | 262 | versionString = nil; 263 | 264 | fuse_ext2Path = kinstalledPath; 265 | fuse_ext2Plist = [NSDictionary dictionaryWithContentsOfFile:fuse_ext2Path]; 266 | if (fuse_ext2Plist == nil) { 267 | fuse_ext2Path = [@"/System" stringByAppendingPathComponent:fuse_ext2Path]; 268 | fuse_ext2Plist = [NSDictionary dictionaryWithContentsOfFile:fuse_ext2Path]; 269 | } 270 | if (fuse_ext2Plist != nil) { 271 | bundleVersion = [fuse_ext2Plist objectForKey:(NSString *) kCFBundleVersionKey]; 272 | if (bundleVersion != nil) { 273 | versionString = [[NSString alloc] initWithString:bundleVersion]; 274 | } 275 | } 276 | 277 | return versionString; 278 | } 279 | 280 | - (void) updateGUI 281 | { 282 | NSString *version; 283 | NSString *available; 284 | NSString *updateString; 285 | NSString *versionString; 286 | 287 | NSLog(@"fuse-ext2.PrefPane: updating gui\n"); 288 | 289 | [spinnerUpdate startAnimation:self]; 290 | 291 | updateString = nil; 292 | version = [self installedVersion]; 293 | available = [self availableVersion]; 294 | versionString = [[NSString alloc] initWithFormat:@"%@ %@", kinstalledString, (version == nil) ? @"Not Installed." : version]; 295 | [aboutLabel setStringValue:kaboutLabelString]; 296 | [installedLabel setStringValue: versionString]; 297 | if (available == nil || [version compare:available] == NSOrderedSame) { 298 | [updateLabel setStringValue:kupdateString]; 299 | [updateButton setTitle:@"Check for Update"]; 300 | doUpdate = NO; 301 | } else { 302 | updateString = [[NSString alloc] initWithFormat:@"%@ %@", kavailableString, available]; 303 | [updateLabel setStringValue:updateString]; 304 | [updateButton setTitle:@"Install Update"]; 305 | doUpdate = YES; 306 | } 307 | 308 | [updateString release]; 309 | [versionString release]; 310 | [version release]; 311 | [available release]; 312 | 313 | [removeButton setEnabled:YES]; 314 | [updateButton setEnabled:YES]; 315 | 316 | [spinnerUpdate stopAnimation:self]; 317 | 318 | NSLog(@"fuse-ext2.PrefPane: gui updated\n"); 319 | } 320 | 321 | - (BOOL) authorize 322 | { 323 | BOOL authorized; 324 | OSStatus status; 325 | AuthorizationRights *kNoRightsSpecified; 326 | 327 | authorized = NO; 328 | 329 | if (authorizationReference != nil) { 330 | authorized = [self copyRights]; 331 | } else { 332 | kNoRightsSpecified = nil; 333 | status = AuthorizationCreate(kNoRightsSpecified, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationReference); 334 | if (status == errAuthorizationSuccess) { 335 | authorized = [self copyRights]; 336 | } 337 | } 338 | return authorized; 339 | } 340 | 341 | - (BOOL) copyRights 342 | { 343 | NSParameterAssert(authorizationReference); 344 | 345 | BOOL isGood; 346 | OSStatus status; 347 | 348 | AuthorizationFlags authorizationFlags = 349 | kAuthorizationFlagDefaults | 350 | kAuthorizationFlagPreAuthorize | 351 | kAuthorizationFlagExtendRights | 352 | kAuthorizationFlagInteractionAllowed; 353 | AuthorizationItem authorizationItem = { 354 | kAuthorizationRightExecute, 355 | 0, 356 | NULL, 357 | 0, 358 | }; 359 | AuthorizationRights authorizationRights = { 360 | 1, 361 | &authorizationItem, 362 | }; 363 | 364 | isGood = NO; 365 | status = AuthorizationCopyRights( 366 | authorizationReference, 367 | &authorizationRights, 368 | kAuthorizationEmptyEnvironment, 369 | authorizationFlags, 370 | NULL); 371 | if (status != errAuthorizationSuccess) { 372 | [self deauthorize]; 373 | } else { 374 | isGood = YES; 375 | } 376 | 377 | return isGood; 378 | } 379 | 380 | - (void) deauthorize 381 | { 382 | if (authorizationReference != nil) { 383 | AuthorizationFree(authorizationReference, kAuthorizationFlagDefaults); 384 | authorizationReference = nil; 385 | } 386 | } 387 | 388 | - (void) mainViewDidLoad 389 | { 390 | [self updateGUI]; 391 | } 392 | 393 | - (void) dealloc 394 | { 395 | [self deauthorize]; 396 | [super dealloc]; 397 | } 398 | 399 | @end 400 | -------------------------------------------------------------------------------- /tools/macosx/prefpane/penguin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alperakcan/fuse-ext2/ae35afb9ab08d87c66c1e021df792b3a7c4308b0/tools/macosx/prefpane/penguin.png --------------------------------------------------------------------------------