FreeBSD FTP mount

Mount a FTP share in your local filesystem is really easy. And it just makes a FTP client feel like dark age software, with a local mount you can freely use your commands over the files and folders in the share.

First install curlftpfs

cd /usr/ports/sysutils/fusefs-curlftpfs/
make install clean

edit /etc/rc.conf and add

fusefs_enable="YES"

and fire it up (actually no daemon here, just a kernel module load), you can see it with kldstat command.

/usr/local/etc/rc.d/fusefs start

Now we can happily mount FTP shares to local filesystem with the curlftpfs command.

curlftpfs ftp://user:pass@ftp.myserver.com /my/local/mount/

If you don’t want the user/pass typed in the command, and probably you don’t because it can be a bad thing ™ (out in the wild waiting for a ps done by other users…), just setup a .netrc file in your home dir with

machine ftp.myserver.com
login myuser
password mypass

then connect without the user/pass like:

curlftpfs ftp://ftp.myserver.com /my/local/mount/

UPDATE

I had some problems with this with a server that was running flawlessly for over a year and it stalled, so i don’t recommend it for production environments, must also test the asynchronous option

5 thoughts on “FreeBSD FTP mount”

  1. ===> fusefs-curlftpfs-0.9.2_3 is marked as broken: does not build.
    *** [install] Error code 1

    Stop in /usr/ports/sysutils/fusefs-curlftpfs.

  2. here is the solution for FreeBSD 9.1+

    echo ‘diff -urN ../fusefs-curlftpfs.orig/Makefile ./Makefile
    — ../fusefs-curlftpfs.orig/Makefile 2012-12-21 19:06:00.000000000 +0900
    +++ ./Makefile 2012-12-21 19:06:28.041610000 +0900
    @@ -26,8 +26,13 @@

    .include

    -.if ${OSVERSION} >= 900000
    -BROKEN= does not build
    +.if ${OSVERSION} >= 1000000
    +EXTRA_PATCHES+= ${FILESDIR}/extra-64-ftpfs.h
    +.else
    +EXTRA_PATCHES+= ${FILESDIR}/extra-32-ftpfs.h
    +.endif
    +.if ${OSVERSION} < 900000
    +EXTRA_PATCHES+= ${FILESDIR}/extra-patch-ftpfs.c
    .endif

    .include
    diff -urN ../fusefs-curlftpfs.orig/files/extra-32-ftpfs.h ./files/extra-32-ftpfs.h
    — ../fusefs-curlftpfs.orig/files/extra-32-ftpfs.h 1970-01-01 09:00:00.000000000 +0900
    +++ ./files/extra-32-ftpfs.h 2012-12-21 18:30:59.000000000 +0900
    @@ -0,0 +1,11 @@
    +— ftpfs.h.orig 2008-04-25 19:32:30.000000000 +0900
    ++++ ftpfs.h 2012-12-21 18:18:20.000000000 +0900
    +@@ -75,7 +75,7 @@
    + do { if (level <= ftpfs.debug) {\
    + int i = 0; \
    + while (++i < level) fprintf(stderr, " "); \
    +- fprintf(stderr, "%ld ", time(NULL));\
    ++ fprintf(stderr, "%d ", time(NULL));\
    + fprintf(stderr, __FILE__ ":%d ", __LINE__);\
    + fprintf(stderr, args);\
    + }\
    diff -urN ../fusefs-curlftpfs.orig/files/extra-64-ftpfs.h ./files/extra-64-ftpfs.h
    — ../fusefs-curlftpfs.orig/files/extra-64-ftpfs.h 1970-01-01 09:00:00.000000000 +0900
    +++ ./files/extra-64-ftpfs.h 2012-12-21 18:50:48.000000000 +0900
    @@ -0,0 +1,11 @@
    +— ftpfs.h.orig 2008-04-25 19:32:30.000000000 +0900
    ++++ ftpfs.h 2012-12-21 18:18:20.000000000 +0900
    +@@ -75,7 +75,7 @@
    + do { if (level <= ftpfs.debug) {\
    + int i = 0; \
    + while (++i write_conn);
    + g_free(fh->full_path);
    + g_free(fh->open_path);
    +- sem_destroy(&fh->data_avail);
    +- sem_destroy(&fh->data_need);
    +- sem_destroy(&fh->data_written);
    +- sem_destroy(&fh->ready);
    ++ if (fh->data_avail) {
    ++ sem_destroy(&fh->data_avail);
    ++ sem_destroy(&fh->data_need);
    ++ sem_destroy(&fh->data_written);
    ++ sem_destroy(&fh->ready);
    ++ }
    + free(fh);
    + }
    +
    diff -urN ../fusefs-curlftpfs.orig/files/patch-ftpfs.c ./files/patch-ftpfs.c
    — ../fusefs-curlftpfs.orig/files/patch-ftpfs.c 2010-01-09 05:02:31.000000000 +0900
    +++ ./files/patch-ftpfs.c 1970-01-01 09:00:00.000000000 +0900
    @@ -1,19 +0,0 @@
    —- ./ftpfs.c.orig 2008-04-30 01:05:47.000000000 +0200
    -+++ ./ftpfs.c 2010-01-08 19:14:39.000000000 +0100
    -@@ -611,10 +611,12 @@
    – curl_easy_cleanup(fh->write_conn);
    – g_free(fh->full_path);
    – g_free(fh->open_path);
    — sem_destroy(&fh->data_avail);
    — sem_destroy(&fh->data_need);
    — sem_destroy(&fh->data_written);
    — sem_destroy(&fh->ready);
    -+ if (fh->data_avail) {
    -+ sem_destroy(&fh->data_avail);
    -+ sem_destroy(&fh->data_need);
    -+ sem_destroy(&fh->data_written);
    -+ sem_destroy(&fh->ready);
    -+ }
    – free(fh);
    – }
    -‘ >> /root/patch.diff
    cd /usr/ports/sysutils/fusefs-curlftpfs/ && patch -p0 < /root/patch.diff && make install clean && rm /rot/patch.diff

    Enjoy!

  3. It says

    Patching file ./Makefile using Plan A…
    patch: **** malformed patch at line 6: .include

    What am I supposed to do?
    Thanks!

    1. Can you please do a ls inside /usr/ports/sysutils/fusefs-curlftpfs ?
      Anyway, i wouldn’t recommend it for a production server without some testing first.

Leave a Reply to AlexCancel reply