merge FreeBSD stuff
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 8d340f9..0bd952e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,6 +2,12 @@
 
 lib_LTLIBRARIES = libfuse.la
 
+if BSD
+mount_source = mount_bsd.c
+else
+mount_source = mount.c
+endif
+
 libfuse_la_SOURCES = 		\
 	fuse.c			\
 	fuse_i.h		\
@@ -12,7 +18,7 @@
 	fuse_mt.c		\
 	fuse_session.c		\
 	helper.c		\
-	mount.c
+	$(mount_source)
 
 libfuse_la_LDFLAGS = -lpthread -version-number 2:5:0 \
 	-Wl,--version-script,fuse_versionscript
diff --git a/lib/fuse.c b/lib/fuse.c
index 5c5eb0a..8966fab 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -18,6 +18,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <limits.h>
 #include <errno.h>
 #include <assert.h>
@@ -804,7 +805,18 @@
             fflush(stdout);
         }
         err = -ENOSYS;
-        if (f->op.mknod && f->op.getattr) {
+        if (S_ISREG(mode) && f->op.create && f->op.getattr) {
+            struct fuse_file_info fi;
+
+            memset(&fi, 0, sizeof(fi));
+            fi.flags = O_CREAT | O_EXCL | O_WRONLY;
+            err = f->op.create(path, mode, &fi);
+            if (!err) {
+                err = lookup_path(f, parent, name, path, &e, &fi);
+                if (f->op.release)
+                    f->op.release(path, &fi);
+            }
+        } else if (f->op.mknod && f->op.getattr) {
             err = f->op.mknod(path, mode, rdev);
             if (!err)
                 err = lookup_path(f, parent, name, path, &e, NULL);
@@ -1937,6 +1949,13 @@
         else
             free(xopts);
     }
+#ifdef __FreeBSD__
+    /*
+     * In FreeBSD, we always use these settings as inode numbers are needed to
+     * make getcwd(3) work.
+     */
+    f->flags |= FUSE_READDIR_INO;
+#endif
     return 0;
 }
 
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index f2ac121..31c2789 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -787,7 +787,7 @@
     req->ch = ch;
 
     if (!f->got_init && in->opcode != FUSE_INIT)
-        fuse_reply_err(req, EPROTO);
+        fuse_reply_err(req, EIO);
     else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
              in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
              in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
diff --git a/lib/helper.c b/lib/helper.c
index d8a522f..79616dc 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -381,8 +381,8 @@
     else
         fuse_instance = NULL;
 
-    fuse_destroy(fuse);
     fuse_unmount(mountpoint);
+    fuse_destroy(fuse);
     free(mountpoint);
 }
 
diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c
new file mode 100644
index 0000000..0111b14
--- /dev/null
+++ b/lib/mount_bsd.c
@@ -0,0 +1,133 @@
+/*
+    FUSE: Filesystem in Userspace
+    Copyright (C) 2005 Csaba Henk <csaba.henk@creo.hu>
+
+    This program can be distributed under the terms of the GNU LGPL.
+    See the file COPYING.LIB.
+*/
+
+#include "fuse.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+#define FUSERMOUNT_PROG         "mount_fusefs"
+
+void fuse_unmount(const char *mountpoint)
+{
+    char dev[128];
+    char *ssc, *umount_cmd;
+    FILE *sf;
+    int rv;
+    char *seekscript =
+    "/usr/bin/fstat  /dev/fuse* |\n"
+    "/usr/bin/awk '{if ($3 == %d) print $10}' |\n"
+    "/usr/bin/sort |\n"
+    "/usr/bin/uniq |\n"
+    "/usr/bin/awk '{ i+=1; if(i > 1){ exit (1); }; printf; }; END{if (i==0) exit (1)}'";
+
+    asprintf(&ssc, seekscript, getpid());
+
+    errno = 0;
+    sf = popen(ssc, "r");
+    if (! sf)
+        return;
+
+    fgets(dev, sizeof(dev), sf);
+    rv = pclose(sf);
+    if (rv)
+        return;
+
+    asprintf(&umount_cmd, "/sbin/umount %s", dev);
+    system(umount_cmd);
+}
+
+int fuse_mount(const char *mountpoint, const char *opts)
+{
+    const char *mountprog = FUSERMOUNT_PROG;
+    int fd;
+    char *fdnam, *dev;
+    int pid;
+
+    fdnam = getenv("FUSE_DEV_FD");
+
+    if (fdnam) {
+        char *ep;
+
+        fd = strtol(fdnam, &ep, 10);
+
+        if (*ep != '\0') {
+            fprintf(stderr, "invalid value given in FUSE_DEV_FD");
+            return -1;
+        }
+
+        if (fd < 0)
+            return -1;
+
+        goto mount;
+    }
+
+    dev = getenv("FUSE_DEV_NAME");
+
+    if (! dev)
+	dev = "/dev/fuse";
+
+    if ((fd = open(dev, O_RDWR)) < 0) {
+        perror("fuse: failed to open fuse device");
+        return -1;
+    }
+
+mount:
+    if (getenv("FUSE_NO_MOUNT") || ! mountpoint)
+        goto out;
+
+    pid = fork();
+
+    if (pid == -1) {
+        perror("fuse: fork() failed");
+        close(fd);
+        return -1;
+    }
+
+    if (pid == 0) {
+        pid = fork();
+
+        if (pid == -1) {
+            perror("fuse: fork() failed");
+            close(fd);
+            exit(1);
+        }
+
+        if (pid == 0) {
+            const char *argv[32];
+            int a = 0;
+
+            if (! fdnam)
+                asprintf(&fdnam, "%d", fd);
+
+            argv[a++] = mountprog;
+            if (opts) {
+                argv[a++] = "-o";
+                argv[a++] = opts;
+            }
+            argv[a++] = fdnam;
+            argv[a++] = mountpoint;
+            argv[a++] = NULL;
+            setenv("MOUNT_FUSEFS_SAFE", "1", 1);
+            execvp(mountprog, (char **) argv);
+            perror("fuse: failed to exec mount program");
+            exit(1);
+        }
+
+        exit(0);
+    }
+
+    waitpid(pid, NULL, 0);
+
+out:
+    return fd;
+}