gphoto2-fuse-fs

How to mount the filesystem of a gphoto2 based digital camera so that you can access the files via "standard" programs like "ls, cat, tar, gthumb, netscape, firefox, etc" rather than just through "gtkam and gphoto2".

Stop press: (Feb 2006): Two other (newer) projects which are better than mine and which have effectively superceded my project:

(1) I've just been told that in the last month or so Philip Langdale has written what you might call "a better version of what I describe below", in which calls to the libgphoto2 api are made directly. Read more about it here or here -- the second link looks more fragile than the first. Philip's version looks easier to build than mine, and works with new version of gphoto2 etc which mine doesn't! :)

(2) In an parallel development, Damion Yates has produced a very featureful Perl based gphoto2 file system project. This one has a clever extension which creates a virtual .xvpics thumbnail directory (for XV) using the thumbnail download feature of gphoto2. Other features: mkdir, rmdir, deleting files, opening (for read only at the moment) files, listing files in directories with correct fileinfo (including perms, sizes and dates).

Both work with recent versions of fuse and gphoto2.


What follows in the remainder of this page is the text of the page as written in November 2004. I retain it for the historical record, but you would be better off using either of the above recommended projects in future!

November 2004:

If you have a camera that communicates with linux via gphoto2 (which itself uses libgphoto2) you may have been annoyed to discover that there is no means of mounting the camera's filesystem as a normal directory. This means that you have to use custom tools like gtkam to view your pictures, and cannot do simple things like "tar up all the pictures and scp them somewhere else" using your favourite common unix commands. At least, not very easily.

In fact I could never get gtkam to work on my machine, and I couldn't understand how it worked, so instead I wrote a 200 line fuse based userland/userspace filesystem that runs on top of gphoto2 and lets you mount your camera's filesystem READ-ONLY on a directory of your choice. Once mounted, you can use it with all your favourite programs gthumb, tar, firefox, netscape etc.

Warning: This page was originally written late in November 2004. I was recently (February 2006) told that this package may not work with newer versions of fuse. Presumably fuse has moved on a bit, and my code would have to be modified somewhat to fit in with whatever the changes are. This may or may not be easy. Perhaps this is a good enough reason to start afresh .. ? I've lost my camera's USB cable at the moment, and have since bought a card reader, so I'm not likely to be able to fix this in the near future. If anyone does find a fix I can post it on this page ...

I have not done anything remotely close to "packaging" my filesystem, or in making it work "well", but I make it available here in case someone/somebody finds it of use. As it stands, it "works" but is fairly slow, as I have not made any serious attempts to buffer transfers from the camera. Furthermore, I could not be bothered to find out how to use libgphoto2 so rather than have a program which makes simple (fast!) calls to a library, I instead have a program that makes slow system calls which fire up the gphoto2 command line interface to libgphoto2. This made it very easy for me to develop, but does not make it the fastest program in the world. If you already have a flash card reader for your gphoto2 based camera, then your best bet is to pull the flash card out of your camera and mount it as a usb filesystem. If you don't have such a card reader, and are still interested, read on!

What you need to do to make my filesystem work:

FIRST: PREPARATION:

  1. Download and install libgphoto2.
  2. Download a SOURCE distribution of gphoto2.
  3. Edit the file

    gphoto2-2.1.4/gphoto2/actions.c

    (obviously your version number may be different to mine!). You should search for the line which says:

    printf(" %5ld KB", (info.file.size+1023) / 1024);

    and change so that it becomes:

    printf(" %d B", info.file.size);
  4. Now compile and install the version of gphoto2 whose source you have just edited.
  5. Check it works by doing something like: connecting your camera to your computer, turning it on, putting it in the right mode, and then issuing a command like

    gphoto2 -L

    which should auto-detect you camera and then return a list of all the files you have stored on it. I just did this on my camera which has about a hundred images stored on it at the moment, and I received this output. Note that if you have made the change to the sourcecode correctly, you will see the file-size for each file in this output reported in bytes (and followed by a "B") rather than the default which is to show it in "rounded up kilobytes" and followed by a "KB". If you see KB then go back and try to modify the source again! You might find that you need to be root (superuser) to have the necessary access rights to your USB ports ...

  6. Download, build and install a distribution of fuse FROM SOURCE! Part of this build involves making a kernel module and this in turn requires a kernel source tree with a configuration that matches the kernel you are running (if my memory serves me rightly).
  7. Check that fuse works by going to their example directory

    cd fuse-2.1-pre0/example

    (your version may be different than mine) and then running the "hello" example filesystem. e.g. to create an example "hello" filesystem mounted on a directory called /tmp/kkk you could do:

    mkdir -p /tmp/kkk
    ./hello -f /tmp/kkk
    after which from another shell you do:

    ls -la /tmp/kkk
    which should show you a "fake" filesystem containing a single file "hello". If you cat this file you should see it contains the message "Hello World". When you kill the "./hello -f /tmp/kkk" program, the fake hello-world filesystem will be unmounted. Very (very!) occasionally this fails (I'm not sure why!) and you need to "unount /tmp/kkk".
  8. If you have got this far then you have a working (slightly modified) gphoto2 installation and a working fuse installation, and so now you are ready to install my gphoto2-fuse-fs.

SECOND: INSTALL MY gphoto2-fuse-fs:

  1. Actually, "install" is a bit of a mis-nomer, as my implementation is actually just an edit of the "hello world" filesystem you just messed with above. What you really need to do to get my filesystem running it to overwrite the hello world example (which you might like to back up!) as follows:
  2. In your source installation of fuse package, edit

    fuse-2.1-pre0/example/Makefile
    as follows:

    Change the line which reads:

    am_hello_OBJECTS = hello.$(OBJEXT)
    so that is reads instead:
    am_hello_OBJECTS = hello.$(OBJEXT) lester.o
    Then add at the end of the Makefile the lines:
    lester.o: lester.cpp
    	g++ -DHAVE_CONFIG_H -I. -I. -I../include -D_FILE_OFFSET_BITS=64 -D_REENTRANT  -Wall -W -g -O2 -MT hello.o -MD -MP -c $^
    
    Here is a copy of my Makefile once I made the above changes. Yours will probably be substantially different to mine, though, as this file was autogenerated during the installation of fuse and so it will be peppered with your directories!

  3. Replace the supplied
    fuse-2.1-pre0/example/hello.c
    with my replacement hello.c.
  4. Create a file
    fuse-2.1-pre0/example/lester.cpp
    identical to lester.cpp.
  5. Create a file
    fuse-2.1-pre0/example/pstream.h
    identical to pstream.h.
  6. Finally issue:
    cd fuse-2.1-pre0/example
    rm -f hello.o
    make
    
  7. That's it! You should now have built my gphoto2-fuse-fs filesystem! If you got error messages when you typed make, then read this.
  8. Test it exactly as before ... it is a drop in replacement for the "hello world" example above. Just remember FIRST to connect your camera to your computer, SECOND check you are logged in a user with sufficient rights to use gphoto2 as checked above, and then FINALLY mount the camera's filesystem on /tmp/kkk with
    ./hello -f /tmp/kkk
    
    which takes a while (sorry! I said it was slow!), produces a lot of debug output, and finally finishes with the message "Handing over to fuse". Here is the full output I see when I mount my own camera.
  9. Test that the mount worked by opening another shell, making sure you are logged in as THE SAME USER who issued the "./hello -f /tmp/kkk" mount above (this is a security requirement of fuse and then by trying something like
    ls -la /tmp/kkk
    
    which gives me this or by trying
    find /tmp/kkk
    which gives me this.
  10. If all that works, then there is nothing more that needs to be done! Remember that any process (gthumb, netscape, gimp etc) that you wish to use the mounted filesystem MUST RUN AS THE SAME USER AS THE USER WHO LAUNCHED "./hello -f /tmp/kkk". This is a security requirement of fuse. I believe you can turn this off by appropriate flags to fuse but I have not tried to do so.

BUGS (See also errata)

I know gphoto2-fuse-fs works for me, but it may well not work for you. If there is enough interest, I may consider trying to make it work better / faster (improve the caching, speed up the mount time, make the fs writeable). However one thing I do NOT expect to do is figure out how to package it better. If anybody else wants to figure out how to do that so that my many lines of instructions above can be rendered much saner then I would much appreciate their input. I am not a package manager!

All the above was tested with my digital camera, a "CANON PowerShot A75", connected via USB. Redhat 9 and a modified 2.4.23 kernel were used. I believe there should be no problem with any 2.4 or 2.6 kernel.

Contact details:

My name is Christopher Lester.

I can be conacted via email at:

lester-@-hep.phy.cam.ac.uk 
in which you should obviously replace "-@-" with plain "@" if you want the email to reach me!