Hello community,

here is the log from the commit of package bindfs for openSUSE:Factory checked 
in at 2016-09-27 13:45:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/bindfs (Old)
 and      /work/SRC/openSUSE:Factory/.bindfs.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "bindfs"

Changes:
--------
--- /work/SRC/openSUSE:Factory/bindfs/bindfs.changes    2016-03-21 
12:45:34.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.bindfs.new/bindfs.changes       2016-09-27 
13:45:31.000000000 +0200
@@ -1,0 +2,7 @@
+Tue Sep 27 07:44:48 UTC 2016 - jeng...@inai.de
+
+- Update to new upstream release 1.13.2
+* Fix bug in readdir() introduced with 1.13.1. This fixes a bug
+  when a bindfs mount is exported over NFS.
+
+-------------------------------------------------------------------

Old:
----
  bindfs-1.13.1.tar.gz

New:
----
  bindfs-1.13.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ bindfs.spec ++++++
--- /var/tmp/diff_new_pack.lGyfxS/_old  2016-09-27 13:45:33.000000000 +0200
+++ /var/tmp/diff_new_pack.lGyfxS/_new  2016-09-27 13:45:33.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           bindfs
-Version:        1.13.1
+Version:        1.13.2
 Release:        0
 Summary:        Mount Directories to other Locations and alter Permission Bits
 License:        GPL-2.0+

++++++ bindfs-1.13.1.tar.gz -> bindfs-1.13.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/.gitignore new/bindfs-1.13.2/.gitignore
--- old/bindfs-1.13.1/.gitignore        2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/.gitignore        2016-09-25 20:32:36.000000000 +0200
@@ -34,6 +34,7 @@
 # Products
 
 src/bindfs
+tests/fcntl_locker
 tests/readdir_inode
 tests/utimens_nofollow
 tests/*.log
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/.travis.yml 
new/bindfs-1.13.2/.travis.yml
--- old/bindfs-1.13.1/.travis.yml       2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/.travis.yml       2016-09-25 20:32:36.000000000 +0200
@@ -4,8 +4,10 @@
 compiler:
   - clang
   - gcc
-script: ./autogen.sh -d && make && sudo make check
+script: ./autogen.sh -d && make && make check && sudo make check
 before_install:
   - sudo apt-get update
   - sudo apt-get install -qq fuse libfuse-dev valgrind
   - sudo /bin/sh -c 'echo user_allow_other > /etc/fuse.conf'
+  - sudo chmod 0777 /dev/fuse
+  - sudo chmod 0777 /etc/fuse.conf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/ChangeLog new/bindfs-1.13.2/ChangeLog
--- old/bindfs-1.13.1/ChangeLog 2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/ChangeLog 2016-09-25 20:32:36.000000000 +0200
@@ -1,3 +1,18 @@
+2016-09-25  Martin Pärtel <martin dot partel at gmail dot com>
+
+       * Fix bug in readdir() introduced with 1.13.1. This fixes a bug when
+         a bindfs mount is exported over NFS (issue #39).
+       * Released 1.13.2
+
+2016-07-31  Martin Pärtel <martin dot partel at gmail dot com>
+
+       * Added --enable-ioctl to address issue #37.
+       * Added --enable-lock-forwarding to address issue #36.
+
+2016-05-03  Martin Pärtel <martin dot partel at gmail dot com>
+
+       * @chenhaiq added --uid-offset and --gid-offset (PR #31). Thanks!
+
 2016-02-17  Martin Pärtel <martin dot partel at gmail dot com>
 
        * Fixed an issue that some users had with reading large
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/configure new/bindfs-1.13.2/configure
--- old/bindfs-1.13.1/configure 2016-02-17 04:52:05.000000000 +0100
+++ new/bindfs-1.13.2/configure 2016-09-25 20:32:40.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for bindfs 1.13.1.
+# Generated by GNU Autoconf 2.69 for bindfs 1.13.2.
 #
 # Report bugs to <martin.par...@gmail.com>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='bindfs'
 PACKAGE_TARNAME='bindfs'
-PACKAGE_VERSION='1.13.1'
-PACKAGE_STRING='bindfs 1.13.1'
+PACKAGE_VERSION='1.13.2'
+PACKAGE_STRING='bindfs 1.13.2'
 PACKAGE_BUGREPORT='martin.par...@gmail.com'
 PACKAGE_URL=''
 
@@ -1327,7 +1327,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures bindfs 1.13.1 to adapt to many kinds of systems.
+\`configure' configures bindfs 1.13.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1397,7 +1397,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of bindfs 1.13.1:";;
+     short | recursive ) echo "Configuration of bindfs 1.13.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1513,7 +1513,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-bindfs configure 1.13.1
+bindfs configure 1.13.2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1791,7 +1791,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by bindfs $as_me 1.13.1, which was
+It was created by bindfs $as_me 1.13.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2655,7 +2655,7 @@
 
 # Define the identity of the package.
  PACKAGE='bindfs'
- VERSION='1.13.1'
+ VERSION='1.13.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12253,7 +12253,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by bindfs $as_me 1.13.1, which was
+This file was extended by bindfs $as_me 1.13.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -12319,7 +12319,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-bindfs config.status 1.13.1
+bindfs config.status 1.13.2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/configure.ac 
new/bindfs-1.13.2/configure.ac
--- old/bindfs-1.13.1/configure.ac      2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/configure.ac      2016-09-25 20:32:36.000000000 +0200
@@ -1,4 +1,4 @@
-AC_INIT([bindfs],[1.13.1],[martin.par...@gmail.com])
+AC_INIT([bindfs],[1.13.2],[martin.par...@gmail.com])
 
 AM_INIT_AUTOMAKE([foreign serial-tests])
 AC_CONFIG_HEADERS([config.h])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/src/bindfs.1 
new/bindfs-1.13.2/src/bindfs.1
--- old/bindfs-1.13.1/src/bindfs.1      2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/src/bindfs.1      2016-09-25 20:32:36.000000000 +0200
@@ -67,6 +67,21 @@
 
 Requires mounting as root.
 
+.TP
+.B \-\-uid\-offset=..., \-o uid\-offset=...
+Works like \-\-map, but adds the given number to all file owner user IDs.
+For instance, \fB--uid-offset=100000\fP causes a file owned by user \fI123\fP
+to be shown as owned by user \fI100123\fP.
+
+For now, this option cannot be used together with \-\-map. Please file an issue
+with the desired semantics if you have a case for using them together.
+
+Requires mounting as root.
+
+.TP
+.B \-\-gid\-offset=..., \-o gid\-offset=...
+Works exactly like \fB--uid-offset\fP but for groups.
+
 
 .SH FILE CREATION POLICY
 New files and directories are created so they are owned by the mounter.
@@ -301,6 +316,31 @@
 The underlying file's ctime will still be updated normally.
 
 .TP
+.B \-\-enable\-lock\-forwarding, \-o enable\-lock\-forwarding
+Forwards \fBflock\fP and \fBfcntl\fP locking requests to the source directory.
+This way, locking a file in the bindfs mount will also lock the file in the
+source directory.
+
+This option \fBmust\fP be used with \fB\-\-multithreaded\fP because otherwise
+bindfs will deadlock as soon as there is lock contention. However, see
+\fB\%BUGS\fP below for caveats about \fB\-\-multithreaded\fP with the current
+implementation.
+
+.TP
+.B \-\-disable\-lock\-forwarding, \-o disable\-lock\-forwarding
+Currently does nothing, but a future release may default to enabling lock
+forwarding. If you depend on this behaviour, it's recommended to set this flag
+explicitly.
+
+.TP
+.B \-\-enable\-ioctl, \-o enable\-ioctl
+Enables forwarding of ioctl, which is needed for some advanced features such as
+append-only files (\fBchattr +a\fP). Note that the ioctl action will be
+performed as the mounter, not the calling user. No efforts are made to check
+whether the calling user would ordinarily have the permissions to make the
+ioctl. This may be a security concern, especially when mounting as root.
+
+.TP
 .B \-\-multithreaded, \-o multithreaded
 Run bindfs in multithreaded mode. While bindfs is designed to be
 otherwise thread-safe, there is currently a race condition that may pose
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/src/bindfs.c 
new/bindfs-1.13.2/src/bindfs.c
--- old/bindfs-1.13.1/src/bindfs.c      2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/src/bindfs.c      2016-09-25 20:32:36.000000000 +0200
@@ -53,6 +53,8 @@
 #endif
 #include <sys/time.h>
 #include <sys/statvfs.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <dirent.h>
@@ -87,6 +89,12 @@
 #define XATTR_APPLE_PREFIX   "com.apple."
 #endif
 
+/* We pessimistically assume signed uid_t and gid_t in our overflow checks,
+   mostly because supporting both cases would require a bunch more code. */
+static const uid_t UID_T_MAX = ((1LL << (sizeof(uid_t)*8-1)) - 1);
+static const gid_t GID_T_MAX = ((1LL << (sizeof(gid_t)*8-1)) - 1);
+static const int UID_GID_OVERFLOW_ERRNO = EIO;
+
 /* SETTINGS */
 static struct Settings {
     const char *progname;
@@ -164,6 +172,13 @@
 
     int ctime_from_mtime;
 
+    int enable_lock_forwarding;
+
+    int enable_ioctl;
+
+    uid_t uid_offset;
+    gid_t gid_offset;
+
 } settings;
 
 
@@ -182,11 +197,17 @@
 static int getattr_common(const char *path, struct stat *stbuf);
 
 /* Chowns a new file if necessary. */
-static void chown_new_file(const char *path, struct fuse_context *fc, int 
(*chown_func)(const char*, uid_t, gid_t));
+static int chown_new_file(const char *path, struct fuse_context *fc, int 
(*chown_func)(const char*, uid_t, gid_t));
 
 /* Unified implementation of unlink and rmdir. */
 static int delete_file(const char *path, int (*target_delete_func)(const char 
*));
 
+/* Apply offsets with overflow checking. */
+static int apply_uid_offset(uid_t *uid);
+static int apply_gid_offset(gid_t *gid);
+static int unapply_uid_offset(uid_t *uid);
+static int unapply_gid_offset(gid_t *gid);
+
 /* FUSE callbacks */
 static void *bindfs_init();
 static void bindfs_destroy(void *private_data);
@@ -218,6 +239,12 @@
                        struct fuse_file_info *fi);
 static int bindfs_write(const char *path, const char *buf, size_t size,
                         off_t offset, struct fuse_file_info *fi);
+static int bindfs_lock(const char *path, struct fuse_file_info *fi, int cmd,
+                       struct flock *lock);
+static int bindfs_flock(const char *path, struct fuse_file_info *fi, int op);
+static int bindfs_ioctl(const char *path, int cmd, void *arg,
+                        struct fuse_file_info *fi, unsigned int flags,
+                        void *data);
 static int bindfs_statfs(const char *path, struct statvfs *stbuf);
 static int bindfs_release(const char *path, struct fuse_file_info *fi);
 static int bindfs_fsync(const char *path, int isdatasync,
@@ -316,6 +343,13 @@
     stbuf->st_uid = usermap_get_uid_or_default(settings.usermap, 
stbuf->st_uid, stbuf->st_uid);
     stbuf->st_gid = usermap_get_gid_or_default(settings.usermap, 
stbuf->st_gid, stbuf->st_gid);
 
+    if (!apply_uid_offset(&stbuf->st_uid)) {
+        return -UID_GID_OVERFLOW_ERRNO;
+    }
+    if (!apply_gid_offset(&stbuf->st_gid)) {
+        return -UID_GID_OVERFLOW_ERRNO;
+    }
+
     /* Report user-defined owner/group if specified */
     if (settings.new_uid != -1)
         stbuf->st_uid = settings.new_uid;
@@ -355,7 +389,7 @@
 
 /* FIXME: another thread may race to see the old owner before the chown is 
done.
           Is there a scenario where this compromises security? Or application 
correctness? */
-static void chown_new_file(const char *path, struct fuse_context *fc, int 
(*chown_func)(const char*, uid_t, gid_t))
+static int chown_new_file(const char *path, struct fuse_context *fc, int 
(*chown_func)(const char*, uid_t, gid_t))
 {
     uid_t file_owner;
     gid_t file_group;
@@ -381,6 +415,13 @@
     file_owner = usermap_get_uid_or_default(settings.usermap_reverse, fc->uid, 
file_owner);
     file_group = usermap_get_gid_or_default(settings.usermap_reverse, fc->gid, 
file_group);
 
+    if (!unapply_uid_offset(&file_owner)) {
+        return -UID_GID_OVERFLOW_ERRNO;
+    }
+    if (!unapply_gid_offset(&file_group)) {
+        return -UID_GID_OVERFLOW_ERRNO;
+    }
+
     if (settings.create_for_uid != -1)
         file_owner = settings.create_for_uid;
     if (settings.create_for_gid != -1)
@@ -391,6 +432,8 @@
             DPRINTF("Failed to chown new file or directory (%d)", errno);
         }
     }
+
+    return 0;
 }
 
 static int delete_file(const char *path, int (*target_delete_func)(const char 
*)) {
@@ -463,6 +506,42 @@
     return 0;
 }
 
+static int apply_uid_offset(uid_t *uid) {
+    if (*uid > UID_T_MAX - settings.uid_offset) {
+        DPRINTF("UID %lld overflowed while applying offset", (long long)*uid);
+        return 0;
+    }
+    *uid += settings.uid_offset;
+    return 1;
+}
+
+static int apply_gid_offset(gid_t *gid) {
+    if (*gid > GID_T_MAX - settings.gid_offset) {
+        DPRINTF("GID %lld overflowed while applying offset", (long long)*gid);
+        return 0;
+    }
+    *gid += settings.gid_offset;
+    return 1;
+}
+
+static int unapply_uid_offset(uid_t *uid) {
+    if (*uid < settings.uid_offset) {
+        DPRINTF("UID %lld underflowed while unapplying offset", (long 
long)*uid);
+        return 0;
+    }
+    *uid -= settings.uid_offset;
+    return 1;
+}
+
+static int unapply_gid_offset(gid_t *gid) {
+  if (*gid < settings.gid_offset) {
+        DPRINTF("GID %lld underflowed while unapplying offset", (long 
long)*gid);
+        return 0;
+    }
+    *gid -= settings.gid_offset;
+    return 1;
+}
+
 
 static void *bindfs_init()
 {
@@ -594,7 +673,6 @@
     }
     de_buf = malloc(offsetof(struct dirent, d_name) + pc_ret + 1);
 
-    seekdir(dp, offset);
     while (1) {
         result = readdir_r(dp, de_buf, &de);
         if (result != 0) {
@@ -609,7 +687,9 @@
         st.st_ino = de->d_ino;
         st.st_mode = de->d_type << 12;
 
-        // See issue #28 for why we pass a 0 offset to `filler`.
+        // See issue #28 for why we pass a 0 offset to `filler` and ignore
+        // `offset`.
+        //
         // Given a 0 offset, `filler` should never return non-zero, so we
         // consider it an error if it does. It is undocumented whether it sets
         // errno in that case, so we zero it first and set it ourself if it
@@ -655,10 +735,10 @@
     }
 
     fc = fuse_get_context();
-    chown_new_file(real_path, fc, &chown);
+    res = chown_new_file(real_path, fc, &chown);
     free(real_path);
 
-    return 0;
+    return res;
 }
 
 static int bindfs_mkdir(const char *path, mode_t mode)
@@ -681,10 +761,10 @@
     }
 
     fc = fuse_get_context();
-    chown_new_file(real_path, fc, &chown);
+    res = chown_new_file(real_path, fc, &chown);
     free(real_path);
 
-    return 0;
+    return res;
 }
 
 static int bindfs_unlink(const char *path)
@@ -717,10 +797,10 @@
     }
 
     fc = fuse_get_context();
-    chown_new_file(real_to, fc, &lchown);
+    res = chown_new_file(real_to, fc, &lchown);
     free(real_to);
 
-    return 0;
+    return res;
 }
 
 static int bindfs_rename(const char *from, const char *to)
@@ -843,6 +923,9 @@
         switch (settings.chown_policy) {
         case CHOWN_NORMAL:
             uid = usermap_get_uid_or_default(settings.usermap_reverse, uid, 
uid);
+            if (!unapply_uid_offset(&uid)) {
+                return -UID_GID_OVERFLOW_ERRNO;
+            }
             break;
         case CHOWN_IGNORE:
             uid = -1;
@@ -856,6 +939,9 @@
         switch (settings.chgrp_policy) {
         case CHGRP_NORMAL:
             gid = usermap_get_gid_or_default(settings.usermap_reverse, gid, 
gid);
+            if (!unapply_gid_offset(&gid)) {
+                return -UID_GID_OVERFLOW_ERRNO;
+            }
             break;
         case CHGRP_IGNORE:
             gid = -1;
@@ -1017,6 +1103,36 @@
     return res;
 }
 
+static int bindfs_lock(const char *path, struct fuse_file_info *fi, int cmd,
+                       struct flock *lock)
+{
+  int res = fcntl(fi->fh, cmd, lock);
+  if (res == -1) {
+    return -errno;
+  }
+  return 0;
+}
+
+static int bindfs_flock(const char *path, struct fuse_file_info *fi, int op)
+{
+    int res = flock(fi->fh, op);
+    if (res == -1) {
+        return -errno;
+    }
+    return 0;
+}
+
+static int bindfs_ioctl(const char *path, int cmd, void *arg,
+                        struct fuse_file_info *fi, unsigned int flags,
+                        void *data)
+{
+    int res = ioctl(fi->fh, cmd, data);
+    if (res == -1) {
+      return -errno;
+    }
+    return res;
+}
+
 static int bindfs_statfs(const char *path, struct statvfs *stbuf)
 {
     int res;
@@ -1262,6 +1378,9 @@
     .open       = bindfs_open,
     .read       = bindfs_read,
     .write      = bindfs_write,
+    .lock       = bindfs_lock,
+    .flock      = bindfs_flock,
+    .ioctl      = bindfs_ioctl,
     .statfs     = bindfs_statfs,
     .release    = bindfs_release,
     .fsync      = bindfs_fsync,
@@ -1292,6 +1411,8 @@
            "  -M      --mirror-only=... Like --mirror but disallow access 
for\n"
            "                            all other users.\n"
            " --map=user1/user2:...      Let user2 see files of user1 as his 
own.\n"
+           " --uid-offset=...           Set file uid = uid + offset.\n"
+           " --gid-offset=...           Set file gid = gid + offset.\n"
            "\n"
            "Permission bits:\n"
            "  -p      --perms=...       Specify permissions, similar to 
chmod\n"
@@ -1335,6 +1456,8 @@
            "  --realistic-permissions   Hide permission bits for actions 
mounter can't do.\n"
            "  --ctime-from-mtime        Read file properties' change time\n"
            "                            from file content modification time.\n"
+           "  --enable-lock-forwarding  Forward locks to the underlying FS.\n"
+           "  --enable-ioctl            Forward ioctl() calls (as the 
mounter).\n"
            "  --hide-hard-links         Always report a hard link count of 
1.\n"
            "  --resolve-symlinks        Resolve symbolic links.\n"
            "  --resolved-symlink-deletion=...  Decide how to delete resolved 
symlinks.\n"
@@ -1375,6 +1498,9 @@
     OPTKEY_XATTR_READ_WRITE,
     OPTKEY_REALISTIC_PERMISSIONS,
     OPTKEY_CTIME_FROM_MTIME,
+    OPTKEY_ENABLE_LOCK_FORWARDING,
+    OPTKEY_DISABLE_LOCK_FORWARDING,
+    OPTKEY_ENABLE_IOCTL,
     OPTKEY_HIDE_HARD_LINKS,
     OPTKEY_RESOLVE_SYMLINKS,
     OPTKEY_MULTITHREADED
@@ -1455,6 +1581,15 @@
     case OPTKEY_CTIME_FROM_MTIME:
         settings.ctime_from_mtime = 1;
         return 0;
+    case OPTKEY_ENABLE_LOCK_FORWARDING:
+        settings.enable_lock_forwarding = 1;
+        return 0;
+    case OPTKEY_DISABLE_LOCK_FORWARDING:
+        settings.enable_lock_forwarding = 0;
+        return 0;
+    case OPTKEY_ENABLE_IOCTL:
+        settings.enable_ioctl = 1;
+        return 0;
     case OPTKEY_HIDE_HARD_LINKS:
         settings.hide_hard_links = 1;
         return 0;
@@ -1732,6 +1867,8 @@
         char *resolved_symlink_deletion;
         int no_allow_other;
         int multithreaded;
+        char *uid_offset;
+        char *gid_offset;
     } od;
 
     #define OPT2(one, two, key) \
@@ -1793,7 +1930,13 @@
 
         OPT2("--realistic-permissions", "realistic-permissions", 
OPTKEY_REALISTIC_PERMISSIONS),
         OPT2("--ctime-from-mtime", "ctime-from-mtime", 
OPTKEY_CTIME_FROM_MTIME),
+        OPT2("--enable-lock-forwarding", "enable-lock-forwarding", 
OPTKEY_ENABLE_LOCK_FORWARDING),
+        OPT2("--disable-lock-forwarding", "disable-lock-forwarding", 
OPTKEY_DISABLE_LOCK_FORWARDING),
+        OPT2("--enable-ioctl", "enable-ioctl", OPTKEY_ENABLE_IOCTL),
         OPT_OFFSET2("--multithreaded", "multithreaded", multithreaded, -1),
+
+        OPT_OFFSET2("--uid-offset=%s", "uid-offset=%s", uid_offset, 0),
+        OPT_OFFSET2("--gid-offset=%s", "gid-offset=%s", gid_offset, 0),
         FUSE_OPT_END
     };
 
@@ -1834,6 +1977,11 @@
     settings.resolved_symlink_deletion_policy = 
RESOLVED_SYMLINK_DELETION_SYMLINK_ONLY;
     settings.realistic_permissions = 0;
     settings.ctime_from_mtime = 0;
+    settings.enable_lock_forwarding = 0;
+    settings.enable_ioctl = 0;
+    settings.uid_offset = 0;
+    settings.gid_offset = 0;
+
     atexit(&atexit_func);
 
     /* Parse options */
@@ -1910,6 +2058,40 @@
         }
     }
 
+    if (od.uid_offset) {
+        if (getuid() != 0) {
+            fprintf(stderr, "Error: You need to be root to use --uid-offset 
!\n");
+            return 1;
+        }
+        if (od.map) {
+            fprintf(stderr, "Error: Cannot use --uid-offset and --map 
together!\n");
+            return 1;
+        }
+        char* endptr = od.uid_offset;
+        settings.uid_offset = strtoul(od.uid_offset, &endptr, 10);
+        if (*endptr != '\0') {
+            fprintf(stderr, "Error: Value of --uid-offset must be a positive 
integer.\n");
+            return 1;
+        }
+    }
+
+    if (od.gid_offset) {
+        if (getuid() != 0) {
+            fprintf(stderr, "Error: You need to be root to use --gid-offset 
!\n");
+            return 1;
+        }
+        if (od.map) {
+            fprintf(stderr, "Error: Cannot use --gid-offset and --map 
together!\n");
+            return 1;
+        }
+        char* endptr = od.gid_offset;
+        settings.gid_offset = strtoul(od.gid_offset, &endptr, 10);
+        if (*endptr != '\0') {
+            fprintf(stderr, "Error: Value of --gid-offset must be a positive 
integer.\n");
+            return 1;
+        }
+    }
+
     /* Parse user and group for new creates */
     if (od.create_for_user) {
         if (getuid() != 0) {
@@ -2038,6 +2220,25 @@
         bindfs_oper.removexattr = NULL;
     }
 
+    /* Check that lock forwarding is not enabled in single-threaded mode. */
+    if (settings.enable_lock_forwarding && !od.multithreaded) {
+        fprintf(stderr, "To use --enable-lock-forwarding, you must use "
+                        "--multithreaded, but see the man page for 
caveats!\n");
+        return 1;
+    }
+
+    /* Remove the locking implementation unless the user has enabled lock
+       forwarding. FUSE implements locking inside the mountpoint by default. */
+    if (!settings.enable_lock_forwarding) {
+        bindfs_oper.lock = NULL;
+        bindfs_oper.flock = NULL;
+    }
+
+    /* Remove the ioctl implementation unless the user has enabled it */
+    if (!settings.enable_ioctl) {
+        bindfs_oper.ioctl = NULL;
+    }
+
     /* fuse_main will daemonize by fork()'ing. The signal handler will 
persist. */
     setup_signal_handling();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/tests/Makefile.am 
new/bindfs-1.13.2/tests/Makefile.am
--- old/bindfs-1.13.1/tests/Makefile.am 2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/tests/Makefile.am 2016-09-25 20:32:36.000000000 +0200
@@ -1,9 +1,10 @@
 
 UNAME_S := $(shell uname -s)
 
-noinst_PROGRAMS = readdir_inode utimens_nofollow
+noinst_PROGRAMS = readdir_inode utimens_nofollow fcntl_locker
 readdir_inode_SOURCES = readdir_inode.c
 utimens_nofollow_SOURCES = utimens_nofollow.c
+fcntl_locker_SOURCES = fcntl_locker.c
 
 TESTS = test_bindfs.rb
 SUBDIRS = internals
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/tests/Makefile.in 
new/bindfs-1.13.2/tests/Makefile.in
--- old/bindfs-1.13.1/tests/Makefile.in 2016-02-17 04:52:06.000000000 +0100
+++ new/bindfs-1.13.2/tests/Makefile.in 2016-09-25 20:32:40.000000000 +0200
@@ -78,7 +78,8 @@
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-noinst_PROGRAMS = readdir_inode$(EXEEXT) utimens_nofollow$(EXEEXT)
+noinst_PROGRAMS = readdir_inode$(EXEEXT) utimens_nofollow$(EXEEXT) \
+       fcntl_locker$(EXEEXT)
 subdir = tests
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
        $(top_srcdir)/depcomp
@@ -91,13 +92,16 @@
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 PROGRAMS = $(noinst_PROGRAMS)
-am_readdir_inode_OBJECTS = readdir_inode.$(OBJEXT)
-readdir_inode_OBJECTS = $(am_readdir_inode_OBJECTS)
-readdir_inode_LDADD = $(LDADD)
+am_fcntl_locker_OBJECTS = fcntl_locker.$(OBJEXT)
+fcntl_locker_OBJECTS = $(am_fcntl_locker_OBJECTS)
+fcntl_locker_LDADD = $(LDADD)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
 am__v_lt_1 = 
+am_readdir_inode_OBJECTS = readdir_inode.$(OBJEXT)
+readdir_inode_OBJECTS = $(am_readdir_inode_OBJECTS)
+readdir_inode_LDADD = $(LDADD)
 am_utimens_nofollow_OBJECTS = utimens_nofollow.$(OBJEXT)
 utimens_nofollow_OBJECTS = $(am_utimens_nofollow_OBJECTS)
 utimens_nofollow_LDADD = $(LDADD)
@@ -135,8 +139,10 @@
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(readdir_inode_SOURCES) $(utimens_nofollow_SOURCES)
-DIST_SOURCES = $(readdir_inode_SOURCES) $(utimens_nofollow_SOURCES)
+SOURCES = $(fcntl_locker_SOURCES) $(readdir_inode_SOURCES) \
+       $(utimens_nofollow_SOURCES)
+DIST_SOURCES = $(fcntl_locker_SOURCES) $(readdir_inode_SOURCES) \
+       $(utimens_nofollow_SOURCES)
 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
        ctags-recursive dvi-recursive html-recursive info-recursive \
        install-data-recursive install-dvi-recursive \
@@ -351,6 +357,7 @@
 UNAME_S := $(shell uname -s)
 readdir_inode_SOURCES = readdir_inode.c
 utimens_nofollow_SOURCES = utimens_nofollow.c
+fcntl_locker_SOURCES = fcntl_locker.c
 TESTS = test_bindfs.rb
 SUBDIRS = internals
 all: all-recursive
@@ -397,6 +404,10 @@
        echo " rm -f" $$list; \
        rm -f $$list
 
+fcntl_locker$(EXEEXT): $(fcntl_locker_OBJECTS) $(fcntl_locker_DEPENDENCIES) 
$(EXTRA_fcntl_locker_DEPENDENCIES) 
+       @rm -f fcntl_locker$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(fcntl_locker_OBJECTS) $(fcntl_locker_LDADD) 
$(LIBS)
+
 readdir_inode$(EXEEXT): $(readdir_inode_OBJECTS) $(readdir_inode_DEPENDENCIES) 
$(EXTRA_readdir_inode_DEPENDENCIES) 
        @rm -f readdir_inode$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(readdir_inode_OBJECTS) $(readdir_inode_LDADD) 
$(LIBS)
@@ -411,6 +422,7 @@
 distclean-compile:
        -rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcntl_locker.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir_inode.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utimens_nofollow.Po@am__quote@
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/tests/common.rb 
new/bindfs-1.13.2/tests/common.rb
--- old/bindfs-1.13.1/tests/common.rb   2016-02-17 04:52:01.000000000 +0100
+++ new/bindfs-1.13.2/tests/common.rb   2016-09-25 20:32:36.000000000 +0200
@@ -66,6 +66,15 @@
     true
 end
 
+def with_umask(umask, &block)
+    old_umask = File.umask(umask)
+    begin
+        block.call
+    ensure
+        File.umask(old_umask)
+    end
+end
+
 def valgrind_options
     opt = ARGV.find {|s| s.start_with?('--valgrind') }
     if opt == nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/tests/fcntl_locker.c 
new/bindfs-1.13.2/tests/fcntl_locker.c
--- old/bindfs-1.13.1/tests/fcntl_locker.c      1970-01-01 01:00:00.000000000 
+0100
+++ new/bindfs-1.13.2/tests/fcntl_locker.c      2016-09-25 20:32:36.000000000 
+0200
@@ -0,0 +1,67 @@
+// Takes two files and exits with 0 if fcntl-locking one fcntl-locks the other.
+// If the files don't fcntl-lock each other, returns 1.
+// If any other error occurs, returns 2.
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(int argc, const char* argv[]) {
+    if (argc != 3) {
+        fprintf(stderr, "expecting exactly two arguments\n");
+        return 2;
+    }
+
+    int fd1 = -1;
+    int fd2 = -1;
+    int result = 2;
+
+    fd1 = open(argv[1], O_RDWR);
+    if (fd1 == -1) {
+        perror("failed to open the first file");
+        goto exit;
+    }
+    fd2 = open(argv[2], O_RDWR);
+    if (fd2 == -1) {
+        perror("failed to open the second file");
+        goto exit;
+    }
+
+    struct flock lock;
+    memset(&lock, 0, sizeof(lock));
+    lock.l_type = F_WRLCK;
+    lock.l_whence = SEEK_SET;
+    lock.l_start = 0;
+    lock.l_len = 0;
+    if (fcntl(fd1, F_SETLK, &lock) == -1) {
+        perror("fcntl F_SETLK on the first file failed");
+        goto exit;
+    }
+
+    memset(&lock, 0, sizeof(lock));
+    lock.l_type = F_WRLCK;
+    lock.l_whence = SEEK_SET;
+    lock.l_start = 0;
+    lock.l_len = 0;
+    if (fcntl(fd2, F_SETLK, &lock) == -1) {
+        if (errno == EACCES || errno == EAGAIN) {
+            result = 0;
+            goto exit;
+        } else {
+            perror("fcntl F_SETLK on the second file failed");
+            goto exit;
+        }
+    } else {
+        result = 1;
+        goto exit;
+    }
+
+exit:
+    close(fd1);
+    close(fd2);
+    return result;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bindfs-1.13.1/tests/test_bindfs.rb 
new/bindfs-1.13.2/tests/test_bindfs.rb
--- old/bindfs-1.13.1/tests/test_bindfs.rb      2016-02-17 04:52:01.000000000 
+0100
+++ new/bindfs-1.13.2/tests/test_bindfs.rb      2016-09-25 20:32:36.000000000 
+0200
@@ -95,11 +95,23 @@
 end
 
 testenv("--create-with-perms=og=r:ogd+x") do
-    touch('src/file')
-    mkdir('src/dir')
+    with_umask(0077) do
+        touch('mnt/file')
+        mkdir('mnt/dir')
+    end
+
+    assert { File.stat('mnt/file').mode & 0777 == 0644 }
+    assert { File.stat('mnt/dir').mode & 0777 == 0755 }
+end
+
+testenv("--create-with-perms=g+rD") do
+    with_umask(0077) do
+        touch('mnt/file')
+        mkdir('mnt/dir')
+    end
 
-    assert { File.stat('mnt/file').mode & 0077 == 0044 }
-    assert { File.stat('mnt/dir').mode & 0077 == 0055 }
+    assert { File.stat('src/file').mode & 0777 == 0640 }
+    assert { File.stat('src/dir').mode & 0777 == 0750 }
 end
 
 testenv("-p 0777 --realistic-permissions", :title => 
'--realistic-permissions') do
@@ -337,6 +349,39 @@
     assert { File.stat('mnt/file1').gid == 1 }
 end
 
+root_testenv("--uid-offset=2") do
+    touch('src/file')
+    chown(1, nil, 'src/file')
+
+    assert { File.stat('mnt/file').uid == 3 }
+end
+
+root_testenv("--gid-offset=2") do
+    touch('src/file')
+    chown(nil, 1, 'src/file')
+
+    assert { File.stat('mnt/file').gid == 3 }
+end
+
+root_testenv("--uid-offset=2 --gid-offset=20", :title => "file creation with 
--uid-offset and --gid-offset") do
+    touch('mnt/file')
+
+    assert { File.stat('mnt/file').uid == 2 }
+    assert { File.stat('mnt/file').gid == 20 }
+    assert { File.stat('src/file').uid == 0 }
+    assert { File.stat('src/file').gid == 0 }
+end
+
+root_testenv("--uid-offset=2 --gid-offset=20", :title => "chown/chgrp with 
--uid-offset and --gid-offset") do
+    touch('src/file')
+    chown(6, 25, 'mnt/file')
+
+    assert { File.stat('mnt/file').uid == 6 }
+    assert { File.stat('mnt/file').gid == 25 }
+    assert { File.stat('src/file').uid == 4 }
+    assert { File.stat('src/file').gid == 5 }
+end
+
 testenv("", :title => "preserves inode numbers") do
     touch('src/file')
     mkdir('src/dir')
@@ -571,6 +616,68 @@
   assert { Dir.entries('mnt/dir').sort == expected_entries.sort }
 end
 
+testenv("--enable-lock-forwarding --multithreaded", :title => "lock 
forwarding") do
+  File.write('src/file', 'some contents for fcntl lockng')
+  # (this test passes with an empty file as well, but this way is clearer)
+
+  # flock
+  File.open('mnt/file') do |f1|
+    File.open('src/file') do |f2|
+      assert { f1.flock(File::LOCK_EX | File::LOCK_NB)  }
+      assert { !f2.flock(File::LOCK_EX | File::LOCK_NB)  }
+      assert { f1.flock(File::LOCK_UN)  }
+
+      assert { f2.flock(File::LOCK_EX | File::LOCK_NB)  }
+      assert { !f1.flock(File::LOCK_EX | File::LOCK_NB)  }
+    end
+    assert { f1.flock(File::LOCK_EX | File::LOCK_NB)  }
+  end
+
+  # fcntl locking
+  system("#{$tests_dir}/fcntl_locker src/file mnt/file")
+  raise "fcntl lock sharing test failed" unless $?.success?
+end
+
+testenv("--disable-lock-forwarding", :title => "no lock forwarding") do
+  File.write('src/file', 'some contents for fcntl lockng')
+
+  # flock
+  File.open('mnt/file') do |f1|
+    File.open('src/file') do |f2|
+      assert { f1.flock(File::LOCK_EX | File::LOCK_NB)  }
+      assert { f2.flock(File::LOCK_EX | File::LOCK_NB)  }
+    end
+    File.open('mnt/file') do |f2|
+      assert { !f2.flock(File::LOCK_EX | File::LOCK_NB)  }
+    end
+  end
+
+  # fcntl locking
+  system("#{$tests_dir}/fcntl_locker src/file mnt/file")
+  raise "fcntl lock sharing test failed" unless $?.exitstatus == 1
+end
+
+# Issue #37
+root_testenv("--enable-ioctl", :title => "append-only ioctl") do
+  touch('mnt/file')
+  system('chattr +a mnt/file')
+  raise 'chattr +a failed' unless $?.success?
+  begin
+    File.open('mnt/file', 'a') do |f|
+      f.write('stuff')
+    end
+    assert { File.read('mnt/file') == 'stuff' }
+    assert_exception(EPERM) { File.write('mnt/file', 'newstuff') }
+  ensure
+    system('chattr -a mnt/file')
+  end
+end
+
+root_testenv("", :title => "ioctl not enabled by default") do
+  touch('mnt/file')
+  assert { `chattr +a mnt/file 2>&1`; !$?.success? }
+end
+
 # FIXME: this stuff around testenv is a hax, and testenv may also exit(), 
which defeats the 'ensure' below.
 # the test setup ought to be refactored. It might well use MiniTest or 
something.
 if Process.uid == 0
@@ -583,7 +690,7 @@
             chown('nobody', nil, 'src/file')
 
             assert { File.stat('mnt/file').uid == $nobody_uid }
-            `usermod root -G bindfs_test_group -a`
+            `usermod -G bindfs_test_group -a root`
             raise "Failed to add root to test group" if !$?.success?
 
             # Cache not refreshed yet


Reply via email to