Better MTP access from linux

Search This thread

J F

Member
May 9, 2012
7
17
An MTP filesystem for linux that I believe works better than anything else currently out there.

http://research.jacquette.com/jmtpfs-exchanging-files-between-android-devices-and-linux/

I tried to make the filesystem implementation robust and as complete as possible within the limits of MTP. Everything except chown, chmod, symlinks, and updating the modification time without actually changing the file should work.

I've only tested it under Fedora 16, but the code is generic enough that it should work on any linux system (and probably Mac OS X as well) with libmtp 1.1.3, fuse, and libmagic.

Give it a try, and let me know if you find any bugs or other issues.

- J
 
Last edited:

ArmanUV

Senior Member
Jan 26, 2012
839
220
Hi. This looks great. I tried mtpfs a couple of weeks ago and found it unreliable and buggy.
I'm trying to use this on mac. I installed gcc 4.7 since xcode command line tools ship with gcc 4.2 which doesn't support C++11.
However I still get this when I run make:
Code:
Making all in src
g++ -DPACKAGE_NAME=\"jmtpfs\" -DPACKAGE_TARNAME=\"jmtpfs\" -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"jmtpfs\ 1.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"jmtpfs\" -DVERSION=\"1.0\" -DHAVE_LIBMAGIC=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_MAGIC_H=1 -I.  -framework IOKit -I/usr/local/Cellar/libmtp/1.1.2/include -I/usr/local/Cellar/libusb-compat/0.1.3/include   -D__DARWIN_64_BIT_INO_T=1 -D__FreeBSD__=10 -D_FILE_OFFSET_BITS=64 -I/usr/local/include/osxfuse/fuse     -g -O2 -std=c++0x -MT jmtpfs-jmtpfs.o -MD -MP -MF .deps/jmtpfs-jmtpfs.Tpo -c -o jmtpfs-jmtpfs.o `test -f 'jmtpfs.cpp' || echo './'`jmtpfs.cpp
cc1plus: error: unrecognized command line option "-std=c++0x"
make[1]: *** [jmtpfs-jmtpfs.o] Error 1
make: *** [all-recursive] Error 1

Any ideas?

---------- Post added at 09:51 PM ---------- Previous post was at 09:34 PM ----------

Ok nevermind that. I had a symlink problem.
I still couldn't compile though:
Code:
jmtpfs.cpp:411:62: error: macro "fuse_main" passed 4 arguments, but takes just 3
jmtpfs.cpp: In function 'int main(int, char**)':
jmtpfs.cpp:411:15: error: 'fuse_main' was not declared in this scope
 

tititake

Member
Dec 10, 2011
39
10
Shanghai
Hi,

I tested on gentoo x64, it worked very well.

Mounted my galaxy nexus as normal user, showed in nautilus as a drive. Copied some flac files to it, so far so good.

Thanks and please keep this going, since mtpfs didn't work for me either.
 

J F

Member
May 9, 2012
7
17
OSX build

With the patch below I got jmtpfs to build under Lion using libmtp, fuse4x, gcc46 (or gcc47), and file (libmagic) installed via macports. I'll include the patch in my next release.

There is still one weird issue though. If jmtpfs is run without the foreground (-f) option, you just get i/o errors when trying to access the device. It looks like something in the way fuse4x is backgrounding the process is messing up libmtp. But with -f it seems to work fine.

Index: src/jmtpfs.cpp
===================================================================
--- src/jmtpfs.cpp (revision 5445)
+++ src/jmtpfs.cpp (working copy)
@@ -22,11 +22,10 @@
#include "ConnectedMtpDevices.h"
#include "mtpFilesystemErrors.h"
#include "Mutex.h"
+#include "FuseHeader.h"

#include <MtpRoot.h>
#include <iostream>
-#include <fuse.h>
-#include <fuse_opt.h>
#include <cstddef>
#include <errno.h>
#include <sstream>
Index: src/MtpNode.h
===================================================================
--- src/MtpNode.h (revision 5445)
+++ src/MtpNode.h (working copy)
@@ -25,7 +25,7 @@
#include "MtpMetadataCache.h"
#include "MtpFilesystemPath.h"
#include "MtpDevice.h"
-#include <fuse.h>
+#include "FuseHeader.h"
#include <time.h>
#include <vector>
#include <string>
Index: src/FuseHeader.h
===================================================================
--- src/FuseHeader.h (revision 0)
+++ src/FuseHeader.h (revision 5447)
@@ -0,0 +1,30 @@
+/*
+ * FuseHeader.h
+ *
+ * Author: Jason Ferrara
+ *
+ * This software is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 3 as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02111-1301, USA.
+ * licensing@fsf.org
+ */
+
+#ifndef FUSEHEADER_H_
+#define FUSEHEADER_H_
+
+#define FUSE_USE_VERSION 26
+#include <fuse.h>
+#include <fuse_opt.h>
+
+
+#endif /* FUSEHEADER_H_ */
Index: src/MtpLocalFileCopy.cpp
===================================================================
--- src/MtpLocalFileCopy.cpp (revision 5445)
+++ src/MtpLocalFileCopy.cpp (working copy)
@@ -22,6 +22,7 @@
#include "mtpFilesystemErrors.h"
#include <sys/stat.h>
#include <iostream>
+#include <unistd.h>

MtpLocalFileCopy::MtpLocalFileCopy(MtpDevice& device, uint32_t id) :
m_device(device), m_remoteId(id), m_needWriteBack(false)
 

J F

Member
May 9, 2012
7
17
I released a version that builds and runs correctly under Mac OS X.

If you follow the link in my first post you'll now see a link to download the new version at the top of the blog post.
 
  • Like
Reactions: ArmanUV

ArmanUV

Senior Member
Jan 26, 2012
839
220
I released a version that builds and runs correctly under Mac OS X.

If you follow the link in my first post you'll now see a link to download the new version at the top of the blog post.


Awesome! I didn't expect such a quick response. I got it working with gcc 4.7 and fuse4x installed using homebrew. I still can't copy/move anything due to permission errors. I tried running with sudo but it wouldn't mount at all. I also caught a couple of crashes: http://pastebin.com/JFgc0n5s http://pastebin.com/1d8FgvVX
 

J F

Member
May 9, 2012
7
17
New release 0.4 with improved Mac OS X compatibility. Follow the link in my first post.

Apparently if you don't lie to the Finder and tell it MTP supports chmod and utime, the Finder throws a fit.

I'm also using the user that started jmtpfs for the uid and gid for the files. This fixes the permissions problems in OS X. And I report the combined free space of all the storage devices as the free space of the mount point. If I report 0 (which is the truth, since the mount point is read only and only contains directory entries for the storage devices, and its each subdirectory of the mount point which is read/write and has its own free space) then the finder assumes there is no free space in any directory under the mount point and refused to copy over files.
 
  • Like
Reactions: ArmanUV

ArmanUV

Senior Member
Jan 26, 2012
839
220
New release 0.4 with improved Mac OS X compatibility. Follow the link in my first post.

Apparently if you don't lie to the Finder and tell it MTP supports chmod and utime, the Finder throws a fit.

I'm also using the user that started jmtpfs for the uid and gid for the files. This fixes the permissions problems in OS X. And I report the combined free space of all the storage devices as the free space of the mount point. If I report 0 (which is the truth, since the mount point is read only and only contains directory entries for the storage devices, and its each subdirectory of the mount point which is read/write and has its own free space) then the finder assumes there is no free space in any directory under the mount point and refused to copy over files.

0.4 compiled with the addition of "#include <unistd.h>" to jmtpfs.cpp and it worked! I was able to send/receive files! Thanks a lot for your efforts. At last we have a viable alternative to Android File Transfer.

Here is a little toturial for less techsavvy Mac owners:

1. Get Xcode from App Store if you haven't already. Open it and go to Preferences>Downloads and install "Command Line Tools".
2. Install homebrew
3. In terminal, run "brew doctor" to check for any issues. Then run "brew update && brew upgrade" to get the latest database.
4. Run this to get gcc 4.7 with C++ support:
Code:
brew install https://raw.github.com/Homebrew/homebrew-dupes/master/gcc.rb
5. Run "brew install fuse4x libmtp libmagic".
6. Run the following to install the fuse kernel extentions:
Code:
sudo cp -rfX /usr/local/Cellar/fuse4x-kext/0.9.0/Library/Extensions/fuse4x.kext /Library/Extensions && sudo chmod +s /Library/Extensions/fuse4x.kext/Support/load_fuse4x
7. Now you should have all the pre requisites installed. Download (fixed) jmtpfs from here and extract it.
8. cd to the extracted directory and run:
Code:
CXX=g++-4.7 CXXFLAGS="-D FUSE_USE_VERSION=25" ./configure --prefix=/usr/local/Cellar/jmptfs/0.4 && make && make install && brew link jmptfs
9. Run "mkdir ~/Android" to create a directory in your homefolder.
10. Finally, run "jmtpfs ~/Android". At this point, you should see a mountpoint called "fuse4x volume 0 jmtpfs" in your home directory, which you can treat as any external harddrive.
 
  • Like
Reactions: maxter3185

Rimher

Senior Member
Aug 20, 2010
413
63
Rome
This is very interesting, but I can't seem to get it to work on Ubuntu Precise 12.04.
This is what I get on the "make" command:

me@me-Precise:~/Downloads/jmtpfs$ make
Making all in src
make[1]: Entering directory `/home/betto/Downloads/jmtpfs/src'
g++ -g -O2 -std=c++0x -lmagic -o jmtpfs jmtpfs-jmtpfs.o jmtpfs-MtpDevice.o jmtpfs-ConnectedMtpDevices.o jmtpfs-Mutex.o jmtpfs-MtpFilesystemPath.o jmtpfs-MtpMetadataCache.o jmtpfs-MtpNode.o jmtpfs-MtpRoot.o jmtpfs-MtpLibLock.o jmtpfs-MtpStorage.o jmtpfs-MtpFolder.o jmtpfs-MtpFile.o jmtpfs-TemporaryFile.o jmtpfs-MtpLocalFileCopy.o -L/usr/local/lib -lmtp -lusb -pthread -lfuse -lrt -ldl
jmtpfs-MtpDevice.o: In function `MtpDevice':
/home/betto/Downloads/jmtpfs/src/MtpDevice.cpp:69: undefined reference to `magic_open'
/home/betto/Downloads/jmtpfs/src/MtpDevice.cpp:72: undefined reference to `magic_load'
/home/betto/Downloads/jmtpfs/src/MtpDevice.cpp:73: undefined reference to `magic_error'
jmtpfs-MtpDevice.o: In function `MtpDevice::SendFile(LIBMTP_file_struct*, int)':
/home/betto/Downloads/jmtpfs/src/MtpDevice.cpp:242: undefined reference to `magic_buffer'
collect2: ld returned 1 exit status
make[1]: *** [jmtpfs] Error 1
make[1]: Leaving directory `/home/betto/Downloads/jmtpfs/src'
make: *** [all-recursive] Error 1

I've installed the libmagic-dev package(or something like that. What are those undefined references? Am I missing some packages??
 
Last edited:

J F

Member
May 9, 2012
7
17
This is very interesting, but I can't seem to get it to work on Ubuntu Precise 12.04.
This is what I get on the "make" command:



I've installed the libmagic-dev package(or something like that. What are those undefined references? Am I missing some packages??

It looks like maybe you ran configure, installed libmagic-dev, and then ran make without rerunning configure.

Do "make distclean;./configure" and make sure configure doesn't report any errors. Then try make again.

If things go right at the final link command there should be a -lmagic at the end of the command line. The -lmagic you see near the beginning of the command line is because of a mistake I made in configure.ac (the LDFLAGS="$LDFLAGS -lmagic" line shouldn't be there), but it has no effect because it comes before the object files that need it.
 
  • Like
Reactions: Rimher

Rimher

Senior Member
Aug 20, 2010
413
63
Rome
It looks like maybe you ran configure, installed libmagic-dev, and then ran make without rerunning configure.

Do "make distclean;./configure" and make sure configure doesn't report any errors. Then try make again.

If things go right at the final link command there should be a -lmagic at the end of the command line. The -lmagic you see near the beginning of the command line is because of a mistake I made in configure.ac (the LDFLAGS="$LDFLAGS -lmagic" line shouldn't be there), but it has no effect because it comes before the object files that need it.
Seems to work correctly now! Thanks a lot =)
The weird thing is that some folders that are available into my Android are not visible through the file system. How's that possible?
 

jd1001

Senior Member
Nov 24, 2011
1,349
567
Ubuntu 12

Hey OP,

When I run the ./configure command I get this output


:/home/jd/Downloads/jmtpfs-0.3# ./configure
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for g++... no
checking for c++... no
checking for gpp... no
checking for aCC... no
checking for CC... no
checking for cxx... no
checking for cc++... no
checking for cl.exe... no
checking for FCC... no
checking for KCC... no
checking for RCC... no
checking for xlC_r... no
checking for xlC... no
checking whether the C++ compiler works... no
configure: error: in `/home/jd/Downloads/jmtpfs-0.3':
configure: error: C++ compiler cannot create executables
See `config.log' for more details

After this when I try make and make install it says

make: *** No targets specified and no makefile found. Stop.
I also tried the latest jmtpfs package too with the same results, what am I doing wrong?


Is this because of the compiler errors above? Any help would really be great. I use Airdroid normally but I would love to try your method. Thank you.
 
Last edited:

jangutter

Member
Dec 2, 2008
12
10
I installed libmagic-dev, autoconf and automake. Before running ./configure, I ran autoreconf, and that also seemed to fix it.

You can do most operations much quicker than with mtpfs, but it's still silly-slow to do something like 'tree'. MTP really sucks in some use-cases. DON'T think of it as a filesystem!
 

ArmanUV

Senior Member
Jan 26, 2012
839
220
I installed libmagic-dev, autoconf and automake. Before running ./configure, I ran autoreconf, and that also seemed to fix it.

You can do most operations much quicker than with mtpfs, but it's still silly-slow to do something like 'tree'. MTP really sucks in some use-cases. DON'T think of it as a filesystem!

I agree. It's way slower than UMS. Granted, on mac, google's own Android File Transfer app works way faster than jmtpfs or mtpfs (it's very buggy and unreliable though)
 

jd1001

Senior Member
Nov 24, 2011
1,349
567
Hey Rimher,

Thanks for that I installed g++

No when I try to run through the ./configure command I get this


checking for FUSE... no
configure: error: Package requirements (fuse >= 2.6) were not met:

No package 'fuse' found

Any ideas?
 

ArmanUV

Senior Member
Jan 26, 2012
839
220
Hey Rimher,

Thanks for that I installed g++

No when I try to run through the ./configure command I get this


checking for FUSE... no
configure: error: Package requirements (fuse >= 2.6) were not met:

No package 'fuse' found

Any ideas?

it's pretty self explanatory. You need to install fuse, as mentioned in OP.
 

Rimher

Senior Member
Aug 20, 2010
413
63
Rome
Hey Rimher,

Thanks for that I installed g++

No when I try to run through the ./configure command I get this


checking for FUSE... no
configure: error: Package requirements (fuse >= 2.6) were not met:

No package 'fuse' found

Any ideas?
sudo apt-get install libfuse-dev
sudo apt-get install libmagic-dev

you have to install a bunch of libraries, not sure if those two are enough, try it
 
  • Like
Reactions: jd1001

Top Liked Posts

  • There are no posts matching your filters.
  • 12
    An MTP filesystem for linux that I believe works better than anything else currently out there.

    http://research.jacquette.com/jmtpfs-exchanging-files-between-android-devices-and-linux/

    I tried to make the filesystem implementation robust and as complete as possible within the limits of MTP. Everything except chown, chmod, symlinks, and updating the modification time without actually changing the file should work.

    I've only tested it under Fedora 16, but the code is generic enough that it should work on any linux system (and probably Mac OS X as well) with libmtp 1.1.3, fuse, and libmagic.

    Give it a try, and let me know if you find any bugs or other issues.

    - J
    2
    OSX build

    With the patch below I got jmtpfs to build under Lion using libmtp, fuse4x, gcc46 (or gcc47), and file (libmagic) installed via macports. I'll include the patch in my next release.

    There is still one weird issue though. If jmtpfs is run without the foreground (-f) option, you just get i/o errors when trying to access the device. It looks like something in the way fuse4x is backgrounding the process is messing up libmtp. But with -f it seems to work fine.

    Index: src/jmtpfs.cpp
    ===================================================================
    --- src/jmtpfs.cpp (revision 5445)
    +++ src/jmtpfs.cpp (working copy)
    @@ -22,11 +22,10 @@
    #include "ConnectedMtpDevices.h"
    #include "mtpFilesystemErrors.h"
    #include "Mutex.h"
    +#include "FuseHeader.h"

    #include <MtpRoot.h>
    #include <iostream>
    -#include <fuse.h>
    -#include <fuse_opt.h>
    #include <cstddef>
    #include <errno.h>
    #include <sstream>
    Index: src/MtpNode.h
    ===================================================================
    --- src/MtpNode.h (revision 5445)
    +++ src/MtpNode.h (working copy)
    @@ -25,7 +25,7 @@
    #include "MtpMetadataCache.h"
    #include "MtpFilesystemPath.h"
    #include "MtpDevice.h"
    -#include <fuse.h>
    +#include "FuseHeader.h"
    #include <time.h>
    #include <vector>
    #include <string>
    Index: src/FuseHeader.h
    ===================================================================
    --- src/FuseHeader.h (revision 0)
    +++ src/FuseHeader.h (revision 5447)
    @@ -0,0 +1,30 @@
    +/*
    + * FuseHeader.h
    + *
    + * Author: Jason Ferrara
    + *
    + * This software is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public License
    + * version 3 as published by the Free Software Foundation.
    + *
    + * This software is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public
    + * License along with this library; if not, write to the
    + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    + * Boston, MA 02111-1301, USA.
    + * licensing@fsf.org
    + */
    +
    +#ifndef FUSEHEADER_H_
    +#define FUSEHEADER_H_
    +
    +#define FUSE_USE_VERSION 26
    +#include <fuse.h>
    +#include <fuse_opt.h>
    +
    +
    +#endif /* FUSEHEADER_H_ */
    Index: src/MtpLocalFileCopy.cpp
    ===================================================================
    --- src/MtpLocalFileCopy.cpp (revision 5445)
    +++ src/MtpLocalFileCopy.cpp (working copy)
    @@ -22,6 +22,7 @@
    #include "mtpFilesystemErrors.h"
    #include <sys/stat.h>
    #include <iostream>
    +#include <unistd.h>

    MtpLocalFileCopy::MtpLocalFileCopy(MtpDevice& device, uint32_t id) :
    m_device(device), m_remoteId(id), m_needWriteBack(false)
    1
    I released a version that builds and runs correctly under Mac OS X.

    If you follow the link in my first post you'll now see a link to download the new version at the top of the blog post.
    1
    New release 0.4 with improved Mac OS X compatibility. Follow the link in my first post.

    Apparently if you don't lie to the Finder and tell it MTP supports chmod and utime, the Finder throws a fit.

    I'm also using the user that started jmtpfs for the uid and gid for the files. This fixes the permissions problems in OS X. And I report the combined free space of all the storage devices as the free space of the mount point. If I report 0 (which is the truth, since the mount point is read only and only contains directory entries for the storage devices, and its each subdirectory of the mount point which is read/write and has its own free space) then the finder assumes there is no free space in any directory under the mount point and refused to copy over files.
    1
    New release 0.4 with improved Mac OS X compatibility. Follow the link in my first post.

    Apparently if you don't lie to the Finder and tell it MTP supports chmod and utime, the Finder throws a fit.

    I'm also using the user that started jmtpfs for the uid and gid for the files. This fixes the permissions problems in OS X. And I report the combined free space of all the storage devices as the free space of the mount point. If I report 0 (which is the truth, since the mount point is read only and only contains directory entries for the storage devices, and its each subdirectory of the mount point which is read/write and has its own free space) then the finder assumes there is no free space in any directory under the mount point and refused to copy over files.

    0.4 compiled with the addition of "#include <unistd.h>" to jmtpfs.cpp and it worked! I was able to send/receive files! Thanks a lot for your efforts. At last we have a viable alternative to Android File Transfer.

    Here is a little toturial for less techsavvy Mac owners:

    1. Get Xcode from App Store if you haven't already. Open it and go to Preferences>Downloads and install "Command Line Tools".
    2. Install homebrew
    3. In terminal, run "brew doctor" to check for any issues. Then run "brew update && brew upgrade" to get the latest database.
    4. Run this to get gcc 4.7 with C++ support:
    Code:
    brew install https://raw.github.com/Homebrew/homebrew-dupes/master/gcc.rb
    5. Run "brew install fuse4x libmtp libmagic".
    6. Run the following to install the fuse kernel extentions:
    Code:
    sudo cp -rfX /usr/local/Cellar/fuse4x-kext/0.9.0/Library/Extensions/fuse4x.kext /Library/Extensions && sudo chmod +s /Library/Extensions/fuse4x.kext/Support/load_fuse4x
    7. Now you should have all the pre requisites installed. Download (fixed) jmtpfs from here and extract it.
    8. cd to the extracted directory and run:
    Code:
    CXX=g++-4.7 CXXFLAGS="-D FUSE_USE_VERSION=25" ./configure --prefix=/usr/local/Cellar/jmptfs/0.4 && make && make install && brew link jmptfs
    9. Run "mkdir ~/Android" to create a directory in your homefolder.
    10. Finally, run "jmtpfs ~/Android". At this point, you should see a mountpoint called "fuse4x volume 0 jmtpfs" in your home directory, which you can treat as any external harddrive.