Hello community,

here is the log from the commit of package unionfs-fuse for openSUSE:Factory 
checked in at 2012-04-12 09:55:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/unionfs-fuse (Old)
 and      /work/SRC/openSUSE:Factory/.unionfs-fuse.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "unionfs-fuse", Maintainer is "[email protected]"

Changes:
--------
--- /work/SRC/openSUSE:Factory/unionfs-fuse/unionfs-fuse.changes        
2011-09-23 12:49:27.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.unionfs-fuse.new/unionfs-fuse.changes   
2012-04-12 09:55:14.000000000 +0200
@@ -1,0 +2,12 @@
+Wed Feb 29 18:15:51 UTC 2012 - [email protected]
+
+- update to 0.25
+  * Alternate way to specify branches
+  * Minor fixes
+
+- update to 0.24
+  * Support for liveCDs / live USB sticks (-o chroot)
+  * Build-in support to change the maximum number of open files
+  * Added recursive directory COW.
+
+-------------------------------------------------------------------

Old:
----
  unionfs-fuse-0.23.tar.bz2

New:
----
  unionfs-fuse-0.25.tar.bz2

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

Other differences:
------------------
++++++ unionfs-fuse.spec ++++++
--- /var/tmp/diff_new_pack.3NZQdb/_old  2012-04-12 09:55:16.000000000 +0200
+++ /var/tmp/diff_new_pack.3NZQdb/_new  2012-04-12 09:55:16.000000000 +0200
@@ -1,7 +1,7 @@
 #
-# spec file for package unionfs-fuse (Version 0.23.0)
+# spec file for package unionfs-fuse
 #
-# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -22,11 +22,11 @@
 BuildRequires:  cmake fuse-devel gcc-c++
 Requires:       fuse
 Summary:        Userspace Unionfs File System
-Version:        0.23.0
+Version:        0.25
 Release:        1
 License:        BSD-3-Clause
 Group:          System/Filesystems
-Source:         %{name}-0.23.tar.bz2
+Source:         %{name}-%{version}.tar.bz2
 Url:            http://podgorny.cz/moin/UnionFsFuse
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 
@@ -42,7 +42,7 @@
 
 
 %prep
-%setup -n %{name}-0.23
+%setup -n %{name}-%{version}
 
 %build
 export CFLAGS=$RPM_OPT_FLAGS

++++++ unionfs-fuse-0.23.tar.bz2 -> unionfs-fuse-0.25.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/.hg_archival.txt 
new/unionfs-fuse-0.25/.hg_archival.txt
--- old/unionfs-fuse-0.23/.hg_archival.txt      2009-03-22 19:58:01.000000000 
+0100
+++ new/unionfs-fuse-0.25/.hg_archival.txt      2012-02-02 13:30:22.000000000 
+0100
@@ -1,2 +1,5 @@
 repo: df08e8e2ff7cdf91cc4424e78375619b9adb17d6
-node: fc458485aac6b1c51e2c97cd019351f1ea6ba692
+node: fdf86815d1e845c798970a08a8f97e1d11645d30
+branch: default
+latesttag: v0.25
+latesttagdistance: 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/.hgtags 
new/unionfs-fuse-0.25/.hgtags
--- old/unionfs-fuse-0.23/.hgtags       2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/.hgtags       2012-02-02 13:30:22.000000000 +0100
@@ -13,3 +13,5 @@
 217b9b9dcb5c52b07c8e83dba7bfac2a284ddd52 v0.21
 4f1cc7ac219b727851314f92761d0fb186de8c95 v0.22
 b492530148c43db8b96ff2191f5752d76106b45a v0.23
+d657e8acbb5bacab8b49a263182635c344639d23 v0.24
+d527e3fdc6cf9db1a83ebe3a51c51f5ef08cb01d v0.25
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/CREDITS 
new/unionfs-fuse-0.25/CREDITS
--- old/unionfs-fuse-0.23/CREDITS       2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/CREDITS       2012-02-02 13:30:22.000000000 +0100
@@ -8,8 +8,16 @@
 Mattias Wadman <[email protected]>
 Lucas C. Villa Real <[email protected]>
 Frank Vanderhallen <[email protected]>
-BlueSloth <[email protected]>
+Jason Cassell (a.k.a. BlueSloth) <[email protected]>
 Raphael Geissert <[email protected]>
+Jason Long <[email protected]>
+Yann E. Morin <[email protected]>
+Alexander Kolesen <[email protected]>
+Pierre Jean Schweitzer <[email protected]>
+Sebastian Pipping <[email protected]>
+Nicolas Dely <[email protected]>
+Julian Andres Klode <[email protected]>
+Mike Kazantsev <[email protected]>
 
 Hashtable routines taken from:
 Christopher Clark <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/Makefile 
new/unionfs-fuse-0.25/Makefile
--- old/unionfs-fuse-0.23/Makefile      2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/Makefile      2012-02-02 13:30:22.000000000 +0100
@@ -1,17 +1,17 @@
-CFLAGS += -Wall
-CPPFLAGS += -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26
-#CPPFLAGS += -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -DHAVE_SETXATTR
-LDFLAGS += 
-DESTDIR?=/usr/local
-
-LIB = -lfuse -lpthread -lm
+PREFIX=/usr/local
+BINDIR=/bin
+SBINDIR=/sbin
 
 build:
-       make -C src/
+       $(MAKE) -C src/
 
 clean:
-       make -C src/ clean
+       $(MAKE) -C src/ clean
 
 install: build
-       cp src/unionfs $(DESTDIR)/sbin/
-       cp man/unionfs-fuse.8 $(DESTDIR)/share/man/man8/
+       install -d $(DESTDIR)$(PREFIX)$(BINDIR)
+       install -d $(DESTDIR)$(PREFIX)$(SBINDIR)
+       install -d $(DESTDIR)$(PREFIX)/share/man/man8
+       install -m 0755 src/unionfs $(DESTDIR)$(PREFIX)$(BINDIR)
+       install -m 0755 mount.unionfs $(DESTDIR)$(PREFIX)$(SBINDIR)
+       install -m 0644 man/unionfs-fuse.8 $(DESTDIR)$(PREFIX)/share/man/man8/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/NEWS new/unionfs-fuse-0.25/NEWS
--- old/unionfs-fuse-0.23/NEWS  2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/NEWS  2012-02-02 13:30:22.000000000 +0100
@@ -1,6 +1,16 @@
+0.25
+- Alternate way to specify branches
+- Minor fixes
+
+0.24
+- Support for liveCDs / live USB sticks (-o chroot)
+- Build-in support to change the maximum number of open files
+- Added recursive directory COW.
+
 0.23
 - remove to_user() and to_root() calls for autorization and use fuse build-in
   default_permissions checks
+- bugfix: rename created wrong whiteout type
 
 0.22
 - Fix a bug reported by Jens Hoelldampf <[email protected]>, in 0.21 cow 
@@ -19,7 +29,7 @@
 - Add a man page.
 
 0.20
-- Fix a critical bug introduced in 0.19 when we disabled threadding
+- Fix a critical bug introduced in 0.19 when we disabled threadding.
 
 0.19
 - Several copy-on-write fixes (readdir, unlink, rmdir, rename).
@@ -29,7 +39,5 @@
 - Add supplementary group support.
 
 0.18
-- First release with copy-on-write (COW) support
+- First release with copy-on-write (COW) support.
 - Many many internal code changes.
-
-- 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unionfs-fuse-0.23/examples/S01a-unionfs-fuse-live-cd.sh 
new/unionfs-fuse-0.25/examples/S01a-unionfs-fuse-live-cd.sh
--- old/unionfs-fuse-0.23/examples/S01a-unionfs-fuse-live-cd.sh 1970-01-01 
01:00:00.000000000 +0100
+++ new/unionfs-fuse-0.25/examples/S01a-unionfs-fuse-live-cd.sh 2012-02-02 
13:30:22.000000000 +0100
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright: Bernd Schubert <[email protected]>
+# BSD license, see LICENSE file for details
+
+FUSE_OPT="-o allow_other,use_ino,suid,dev,nonempty"
+CHROOT_PATH="/tmp/unionfs"
+UNION_OPT="-ocow,chroot=$CHROOT_PATH,max_files=32768"
+
+UBIN=/usr/bin/unionfs-fuse
+
+mount -t proc proc /proc
+mount -t tmpfs tmpfs /tmp
+
+mkdir -p $CHROOT_PATH/root
+mkdir -p $CHROOT_PATH/rw
+mkdir -p /tmp/union
+
+mount --bind / $CHROOT_PATH/root
+
+$UBIN $FUSE_OPT $UNION_OPT /rw=RW:/root=RO /tmp/union
+
+mount -t proc proc /tmp/union/proc
+
+cd /tmp/union
+mkdir oldroot
+pivot_root . oldroot
+
+init q
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/examples/rc.local.omit-pid.sh 
new/unionfs-fuse-0.25/examples/rc.local.omit-pid.sh
--- old/unionfs-fuse-0.23/examples/rc.local.omit-pid.sh 1970-01-01 
01:00:00.000000000 +0100
+++ new/unionfs-fuse-0.25/examples/rc.local.omit-pid.sh 2012-02-02 
13:30:22.000000000 +0100
@@ -0,0 +1,26 @@
+#!/bin/sh -e
+#
+# rc.local
+#
+# This script is executed at the end of each multiuser runlevel.
+# Make sure that the script will "exit 0" on success or any other
+# value on error.
+#
+# In order to enable or disable this script just change the execution
+# bits.
+#
+# By default this script does nothing.
+
+# dont't kill unionfs-fuse
+dir=/lib/init/rw/sendsigs.omit.d
+[ ! -d $dir ] || omitdir=$dir
+dir=/var/run/sendsigs.omit.d
+[ ! -d $dir ] || omitdir=$dir
+
+if [ -n "$omitdir" ]; then
+       for i in `ps ax |grep unionfs | grep -v grep | awk '{print $1}'`; do 
+               echo $i >${omitdir}/unionfs.$i; 
+       done
+fi
+
+exit 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/examples/unionfs-fuse-nfs-root 
new/unionfs-fuse-0.25/examples/unionfs-fuse-nfs-root
--- old/unionfs-fuse-0.23/examples/unionfs-fuse-nfs-root        2009-03-22 
19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/examples/unionfs-fuse-nfs-root        2012-02-02 
13:30:22.000000000 +0100
@@ -87,7 +87,7 @@
 mkdir -p /${UPATH}/host/root
 mount -n -omode=0655 -t tmpfs tmpfs /${UPATH}/host/root
 
-function unionmount()
+unionmount()
 {
        dir=$1
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/man/unionfs-fuse.8 
new/unionfs-fuse-0.25/man/unionfs-fuse.8
--- old/unionfs-fuse-0.23/man/unionfs-fuse.8    2009-03-22 19:58:01.000000000 
+0100
+++ new/unionfs-fuse-0.25/man/unionfs-fuse.8    2012-02-02 13:30:22.000000000 
+0100
@@ -41,14 +41,30 @@
 \fB\-o noinitgroups
 Since version 0.23 without any effect, just left over for compatibility.
 Might be removed in future versions.
+.TP
+\fB\-o chroot=path
+Path to chroot into. By using this option unionfs-fuse
+may be used for live CDs or live USB sticks, etc. So it can serve
+"/" as filesystem. If you do not specify this option and try to use
+it for "/" it will deadlock on calling 'pivot_root'. 
+If you do set this option, you also need to specify the branches relativly
+to the given chroot directory. See examples/S01a-unionfs-fuse-live-cd.sh
+for an example.
+.TP
+\fB\-o max_files=number
+Maximum number of open files. Most system have a default of 1024 open
+files per process. For example if unionfs-fuse servs "/" applications like
+KDE or GNOME might have much more open files, which will make the unionfs-fuse 
+process to exceed this limit. Suggested for "/" is >16000 or even >32000 files.
+If this limit exceeds unionfs-fuse will not be able to open further files.
 .SH "Options to libfuse"
 There are several further options available, which don't directly apply to
 unionfs, but to libfuse. Please run "unionfs-fuse --help" to see these.
 We already set the "-o default-permissions" options on our own.
 .SH "EXAMPLES"
 .Vb 5
-\& unionfs\-fuse \-o cow \-o allow_other \e
-\&              \-o use_ino \-o nonempty \e
+\& unionfs\-fuse \-o cow,max_files=32768 \e
+\&              -o allow_other,use_ino,suid,dev,nonempty \e
 \&              /u/host/etc=RW:/u/group/etc=RO:/u/common/etc=RO \e
 \&              /u/union/etc
 .Ve
@@ -77,11 +93,10 @@
 these scripts in the group meta directory.
 .SH "KNOWN ISSUES"
 .Vb 5
-\&1) Presently it is not possible to create a union for /\. This is work in 
progress. 
-\&2) Another issue is that presently there is no support for read-only branches
+\&1) Another issue is that presently there is no support for read-only branches
 when copy-on-write is disabled, thus, -ocow is NOT specified! Support for 
 that might be added in later releases.
-.VE
+.Ve
 .SH "AUTHORS"
 .B unionfs\-fuse
 Original implemention by Radek Podgorny <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/mount.unionfs 
new/unionfs-fuse-0.25/mount.unionfs
--- old/unionfs-fuse-0.23/mount.unionfs 1970-01-01 01:00:00.000000000 +0100
+++ new/unionfs-fuse-0.25/mount.unionfs 2012-02-02 13:30:22.000000000 +0100
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+label=$1
+mpoint=$2
+shift 3
+dirs=${@##*,dirs=}
+dirs=${dirs/,/:}
+mount.fuse "unionfs#$dirs" "$mpoint" -o ${@%%,dirs=*} 
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/Makefile 
new/unionfs-fuse-0.25/src/Makefile
--- old/unionfs-fuse-0.23/src/Makefile  2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/Makefile  2012-02-02 13:30:22.000000000 +0100
@@ -1,9 +1,12 @@
 CFLAGS += -Wall
-CPPFLAGS += -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26
-#CPPFLAGS += -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -DHAVE_SETXATTR
+CPPFLAGS += $(shell pkg-config --cflags fuse)
+CPPFLAGS += -DFUSE_USE_VERSION=26
+CPPFLAGS += -DHAVE_SETXATTR
+
 LDFLAGS += 
 
-LIB = -lfuse -lpthread -lm
+LIB = $(shell pkg-config --libs fuse)
+LIB += -lm  # For ceil(3)
 
 HASHTABLE_OBJ = hashtable.o hashtable_itr.o
 UNIONFS_OBJ = unionfs.o stats.o opts.o debug.o findbranch.o readdir.o 
general.o unlink.o rmdir.o cow.o cow_utils.o string.o
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/cow.c 
new/unionfs-fuse-0.25/src/cow.c
--- old/unionfs-fuse-0.23/src/cow.c     2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/cow.c     2012-02-02 13:30:22.000000000 +0100
@@ -15,6 +15,7 @@
 #include <locale.h>
 #include <errno.h>
 #include <stdio.h>
+#include <dirent.h>
 
 #include "opts.h"
 #include "findbranch.h"
@@ -162,7 +163,7 @@
                        res = copy_link(&cow);
                        break;
                case S_IFDIR:
-                       res = path_create(path, branch_ro, branch_rw);
+                       res = copy_directory(path, branch_ro, branch_rw);
                        break;
                case S_IFBLK:
                case S_IFCHR:
@@ -180,3 +181,40 @@
 
        return res;
 }
+
+/**
+ * copy a directory between branches (includes all contents of the directory)
+ */
+int copy_directory(const char *path, int branch_ro, int branch_rw) {
+       DBG_IN();
+
+       /* create the directory on the destination branch */
+       int res = path_create(path, branch_ro, branch_rw);
+       if (res != 0) {
+               return res;
+       }
+
+       /* determine path to source directory on read-only branch */
+       char from[PATHLEN_MAX];
+       if (BUILD_PATH(from, uopt.branches[branch_ro].path, path)) return 1;
+
+       DIR *dp = opendir(from);
+       if (dp == NULL) return 1;
+
+       struct dirent *de;
+       while ((de = readdir(dp)) != NULL) {
+               if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 
0) continue;
+
+               char member[PATHLEN_MAX];
+               if (BUILD_PATH(member, path, de->d_name)) {
+                       res = 1;
+                       break;
+               }
+               res = cow_cp(member, branch_ro, branch_rw);
+               if (res != 0) break;
+       }
+
+       closedir(dp);
+       return res;
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/cow.h 
new/unionfs-fuse-0.25/src/cow.h
--- old/unionfs-fuse-0.23/src/cow.h     2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/cow.h     2012-02-02 13:30:22.000000000 +0100
@@ -12,5 +12,6 @@
 int cow_cp(const char *path, int branch_ro, int branch_rw);
 int path_create(const char *path, int nbranch_ro, int nbranch_rw);
 int path_create_cutlast(const char *path, int nbranch_ro, int nbranch_rw);
+int copy_directory(const char *path, int branch_ro, int branch_rw);
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/cow_utils.c 
new/unionfs-fuse-0.25/src/cow_utils.c
--- old/unionfs-fuse-0.23/src/cow_utils.c       2009-03-22 19:58:01.000000000 
+0100
+++ new/unionfs-fuse-0.25/src/cow_utils.c       2012-02-02 13:30:22.000000000 
+0100
@@ -194,7 +194,7 @@
                }
                if (rcount < 0) {
                        usyslog(LOG_WARNING,   "copy failed: %s", 
cow->from_path);
-                       return 1;
+                       rval = 1;
                }
        }
 
@@ -245,8 +245,10 @@
                usyslog(LOG_WARNING,   "readlink: %s", cow->from_path);
                return (1);
        }
+
+       link[len] = '\0';
        
-       if (symlink(cow->from_path, cow->to_path)) {
+       if (symlink(link, cow->to_path)) {
                usyslog(LOG_WARNING,   "symlink: %s", link);
                return (1);
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/findbranch.c 
new/unionfs-fuse-0.25/src/findbranch.c
--- old/unionfs-fuse-0.23/src/findbranch.c      2009-03-22 19:58:01.000000000 
+0100
+++ new/unionfs-fuse-0.25/src/findbranch.c      2012-02-02 13:30:22.000000000 
+0100
@@ -109,8 +109,7 @@
 
        int branch = find_rw_branch_cow(path);
 
-       if (branch >= 0 || (branch < 0 && errno != ENOENT))
-               return branch;
+       if (branch >= 0 || (branch < 0 && errno != ENOENT)) return branch;
 
        DBG("Check for parent directory\n");
 
@@ -128,6 +127,7 @@
 
        if (!uopt.cow_enabled) {
                // So path exists, but is not writable.
+               branch = -1;
                errno = EACCES;
                goto out;
        }
@@ -137,12 +137,12 @@
 
        // no writable branch found, we must return an error
        if (branch_rw < 0) {
+               branch = -1;
                errno = EACCES;
                goto out;
        }
 
-       if (path_create(dname, branch, branch_rw) == 0)
-               branch = branch_rw; // path successfully copied
+       if (path_create(dname, branch, branch_rw) == 0) branch = branch_rw; // 
path successfully copied
 
 out:
        free(dname);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/general.c 
new/unionfs-fuse-0.25/src/general.c
--- old/unionfs-fuse-0.23/src/general.c 2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/general.c 2012-02-02 13:30:22.000000000 +0100
@@ -60,8 +60,7 @@
        if (!uopt.cow_enabled) return false;
 
        char whiteoutpath[PATHLEN_MAX];
-       if (BUILD_PATH(whiteoutpath, uopt.branches[branch].path, METADIR, path))
-               return false;
+       if (BUILD_PATH(whiteoutpath, uopt.branches[branch].path, METADIR, 
path)) return false;
 
        char *walk = whiteoutpath;
 
@@ -105,12 +104,11 @@
        int i;
        for (i = 0; i <= maxbranch; i++) {
                char p[PATHLEN_MAX];
-               if (BUILD_PATH(p, uopt.branches[i].path, METADIR, path, 
HIDETAG))
-                       return 1;
+               if (BUILD_PATH(p, uopt.branches[i].path, METADIR, path, 
HIDETAG)) return 1;
 
                switch (path_is_dir(p)) {
-                       case IS_FILE: unlink (p); break;
-                       case IS_DIR:  rmdir  (p); break;
+                       case IS_FILE: unlink(p); break;
+                       case IS_DIR: rmdir(p); break;
                        case NOT_EXISTING: continue;
                }
        }
@@ -150,8 +148,7 @@
        path_create_cutlast(metapath, branch_rw, branch_rw);
 
        char p[PATHLEN_MAX];
-       if (BUILD_PATH(p, uopt.branches[branch_rw].path, metapath, HIDETAG))
-               return -1;
+       if (BUILD_PATH(p, uopt.branches[branch_rw].path, metapath, HIDETAG)) 
return -1;
 
        int res;
        if (mode == WHITEOUT_FILE) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/hashtable_itr.c 
new/unionfs-fuse-0.25/src/hashtable_itr.c
--- old/unionfs-fuse-0.23/src/hashtable_itr.c   2009-03-22 19:58:01.000000000 
+0100
+++ new/unionfs-fuse-0.25/src/hashtable_itr.c   2012-02-02 13:30:22.000000000 
+0100
@@ -35,18 +35,6 @@
 }
 
 /*****************************************************************************/
-/* key      - return the key of the (key,value) pair at the current position */
-/* value    - return the value of the (key,value) pair at the current position 
*/
-
-void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{ return i->e->k; }
-
-void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{ return i->e->v; }
-
-/*****************************************************************************/
 /* advance - advance the iterator to the next element
  *           returns zero if advanced to end of table */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/hashtable_itr.h 
new/unionfs-fuse-0.25/src/hashtable_itr.h
--- old/unionfs-fuse-0.23/src/hashtable_itr.h   2009-03-22 19:58:01.000000000 
+0100
+++ new/unionfs-fuse-0.25/src/hashtable_itr.h   2012-02-02 13:30:22.000000000 
+0100
@@ -29,18 +29,16 @@
  * - return the value of the (key,value) pair at the current position */
 
 extern inline void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{
-    return i->e->k;
+hashtable_iterator_key(struct hashtable_itr *i) {
+       return i->e->k;
 }
 
 /*****************************************************************************/
 /* value - return the value of the (key,value) pair at the current position */
 
 extern inline void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{
-    return i->e->v;
+hashtable_iterator_value(struct hashtable_itr *i) {
+       return i->e->v;
 }
 
 /*****************************************************************************/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/opts.c 
new/unionfs-fuse-0.25/src/opts.c
--- old/unionfs-fuse-0.23/src/opts.c    2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/opts.c    2012-02-02 13:30:22.000000000 +0100
@@ -12,14 +12,40 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 #include "opts.h"
 #include "stats.h"
 #include "version.h"
+#include "string.h"
 
+/**
+ * Set the maximum number of open files
+ */
+int set_max_open_files(const char *arg)
+{
+       struct rlimit rlim;
+       unsigned long max_files;
+       if (sscanf(arg, "max_files=%ld\n", &max_files) != 1) {
+               fprintf(stderr, "%s Converting %s to number failed, 
aborting!\n",
+                       __func__, arg);
+               exit(1);
+       }
+       rlim.rlim_cur = max_files;
+       rlim.rlim_max = max_files;
+       if (setrlimit(RLIMIT_NOFILE, &rlim)) {
+               fprintf(stderr, "%s: Setting the maximum number of files 
failed: %s\n",
+                       __func__, strerror(errno));
+               exit(1);
+       }
+
+       return 0;
+}
 
-uopt_t uopt;
 
+uopt_t uopt;
 
 void uopt_init() {
        memset(&uopt, 0, sizeof(uopt_t)); // initialize options with zeros first
@@ -28,10 +54,10 @@
 }
 
 /**
- * Take a relative path as argument and return the absolute path by using the 
+ * Take a relative path as argument and return the absolute path by using the
  * current working directory. The return string is malloc'ed with this 
function.
  */
-static char *make_absolute(char *relpath) {
+char *make_absolute(char *relpath) {
        // Already an absolute path
        if (*relpath == '/') return relpath;
 
@@ -47,10 +73,9 @@
                return NULL;
        }
 
-       // 3 due to: +1 for '/' between cwd and relpath
+       // 2 due to: +1 for '/' between cwd and relpath
        //           +1 for trailing '/'
-       //           +1 for terminating '\0'
-       int abslen = cwdlen + strlen(relpath) + 3;
+       int abslen = cwdlen + strlen(relpath) + 2;
        if (abslen > PATHLEN_MAX) {
                fprintf(stderr, "Absolute path too long!\n");
                return NULL;
@@ -61,10 +86,9 @@
                fprintf(stderr, "%s: malloc failed\n", __func__);
                exit(1); // still at early stage, we can abort
        }
-
-       // the trailing '/' is important so that we are sure later on the
-       // directory components are properly seperated
-       snprintf(abspath, abslen, "%s/%s/", cwd, relpath);
+       
+       // the ending required slash is added later by add_trailing_slash()
+       snprintf(abspath, abslen, "%s/%s", cwd, relpath);
 
        return abspath;
 }
@@ -73,7 +97,7 @@
  * Add a trailing slash at the end of a branch. So functions using this
  * path don't have to care about this slash themselves.
  **/
-static char *add_trailing_slash(char *path) {
+char *add_trailing_slash(char *path) {
        int len = strlen(path);
        if (path[len - 1] == '/') {
                return path; // no need to add a slash, already there
@@ -109,8 +133,6 @@
        // for string manipulations it is important to copy the string, 
otherwise
        // make_absolute() and add_trailing_slash() will corrupt our input 
(parse string)
        uopt.branches[uopt.nbranches].path = strdup(res);
-       uopt.branches[uopt.nbranches].path = 
make_absolute(uopt.branches[uopt.nbranches].path);
-       uopt.branches[uopt.nbranches].path = 
add_trailing_slash(uopt.branches[uopt.nbranches].path);
        uopt.branches[uopt.nbranches].rw = 0;
 
        res = strsep(ptr, "=");
@@ -129,10 +151,11 @@
 }
 
 /**
- * Options without any -X prefix, so these options define our branch paths.
+ * These options define our branch paths.
  * example arg string: "branch1=RW:branch2=RO:branch3=RO"
  */
 static int parse_branches(const char *arg) {
+       // the last argument is  our mountpoint, don't take it as branch!
        if (uopt.nbranches) return 0;
 
        // We don't free the buf as parts of it may go to branches
@@ -150,6 +173,40 @@
        return uopt.nbranches;
 }
 
+/**
+  * fuse passes arguments with the argument prefix, e.g.
+  * "-o chroot=/path/to/chroot/" will give us "chroot=/path/to/chroot/"
+  * and we need to cut off the "chroot=" part
+  * NOTE: If the user specifies a relative path of the branches
+  *       to the chroot, it is absolutely required
+  *       -o chroot=path is provided before specifying the braches!
+  */
+char * get_chroot(const char *arg)
+{
+       char *str = index(arg, '=');
+
+       if (!str) {
+               fprintf(stderr, "-o chroot parameter not properly specified, 
aborting!\n");
+               exit(1); // still early phase, we can abort
+       }
+
+       if (strlen(str) < 3) {
+               fprintf(stderr, "Chroot path has not sufficient characters, 
aborting!\n");
+               exit(1);
+       }
+
+       str++; // just jump over the '='
+
+       // copy of the given parameter, just in case something messes around
+       // with command line parameters later on
+       str = strdup(str);
+       if (!str) {
+               fprintf(stderr, "strdup failed: %s Aborting!\n", 
strerror(errno));
+               exit(1);
+       }
+       return str;
+}
+
 static void print_help(const char *progname) {
        printf(
        "unionfs-fuse version "VERSION"\n"
@@ -164,14 +221,65 @@
        "    -V   --version         print version\n"
        "\n"
        "UnionFS options:\n"
+       "    -o dirs=branch[=RO/RW][:branch...]\n"
+       "                           alternate way to specify directories to 
merge\n"
        "    -o cow                 enable copy-on-write\n"
        "    -o stats               show statistics in the file 'stats' under 
the\n"
        "                           mountpoint\n"
-       "    -o statfs_omit_ro      also count blocks of ro-branches\n"
+       "    -o statfs_omit_ro      do not count blocks of ro-branches\n"
+       "    -o chroot=path         chroot into this path. Use this if you \n"
+        "                           want to have a union of \"/\" \n"
+       "    -o max_files=number    Increase the maximum number of open files\n"
        "\n",
        progname);
 }
 
+/**
+  * This method is to post-process options once we know all of them
+  */
+void unionfs_post_opts(void) {
+       // chdir to the given chroot, we
+       if (uopt.chroot) {
+               int res = chdir(uopt.chroot);
+               if (res) {
+                       fprintf(stderr, "Chdir to %s failed: %s ! Aborting!\n",
+                                 uopt.chroot, strerror(errno));
+                       exit(1);
+               }
+       }
+
+       // Make the pathes absolute and add trailing slashes
+       int i;
+       for (i = 0; i<uopt.nbranches; i++) {
+               // if -ochroot= is specified, the path has to be given absolute
+               // or relative to the chroot, so no need to make it absolute
+               // also won't work, since we are not yet in the chroot here
+               if (!uopt.chroot) {
+                       uopt.branches[i].path = 
make_absolute(uopt.branches[i].path);
+               }
+               uopt.branches[i].path = 
add_trailing_slash(uopt.branches[i].path);
+
+               // Prevent accidental umounts. Especially system shutdown 
scripts tend
+               // to umount everything they can. If we don't have an open file 
descriptor,
+               // this might cause unexpected behaviour.
+               char path[PATHLEN_MAX];
+
+               if (!uopt.chroot) {
+                       BUILD_PATH(path, uopt.branches[i].path);
+               } else {
+                       BUILD_PATH(path, uopt.chroot, uopt.branches[i].path);
+               }
+
+               int fd = open(path, O_RDONLY);
+               if (fd == -1) {
+                       fprintf(stderr, "\nFailed to open %s: %s. 
Aborting!\n\n",
+                               path, strerror(errno));
+                       exit(1);
+               }
+               uopt.branches[i].fd = fd;
+       }
+}
+
 int unionfs_opt_proc(void *data, const char *arg, int key, struct fuse_args 
*outargs) {
        (void)data;
 
@@ -183,6 +291,12 @@
                        if (res > 0) return 0;
                        uopt.retval = 1;
                        return 1;
+               case KEY_DIRS:
+                       // skip the "dirs="
+                       res = parse_branches(arg+5);
+                       if (res > 0) return 0;
+                       uopt.retval = 1;
+                       return 1;
                case KEY_STATS:
                        uopt.stats_enabled = 1;
                        return 0;
@@ -195,6 +309,12 @@
                case KEY_NOINITGROUPS:
                        // option only for compatibility with older versions
                        return 0;
+               case KEY_CHROOT:
+                       uopt.chroot = get_chroot(arg);
+                       return 0;
+               case KEY_MAX_FILES:
+                       set_max_open_files(arg);
+                       return 0;
                case KEY_HELP:
                        print_help(outargs->argv[0]);
                        fuse_opt_add_arg(outargs, "-ho");
@@ -202,6 +322,9 @@
                        return 0;
                case KEY_VERSION:
                        printf("unionfs-fuse version: "VERSION"\n");
+#ifdef HAVE_SETXATTR
+                       printf("(compiled with xattr support)\n");
+#endif
                        uopt.doexit = 1;
                        return 1;
                default:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/opts.h 
new/unionfs-fuse-0.25/src/opts.h
--- old/unionfs-fuse-0.23/src/opts.h    2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/opts.h    2012-02-02 13:30:22.000000000 +0100
@@ -22,16 +22,21 @@
 
        bool stats_enabled;
        bool cow_enabled;
-       bool statfs_omit_ro; 
+       bool statfs_omit_ro;
        int doexit;
        int retval;
+       char *chroot;           // chroot we might go into
+
 } uopt_t;
 
 enum {
+       KEY_DIRS,
        KEY_STATS,
        KEY_COW,
        KEY_STATFS_OMIT_RO,
        KEY_NOINITGROUPS,
+       KEY_CHROOT,
+       KEY_MAX_FILES,
        KEY_HELP,
        KEY_VERSION
 };
@@ -42,6 +47,6 @@
 
 void uopt_init();
 int unionfs_opt_proc(void *data, const char *arg, int key, struct fuse_args 
*outargs);
-
+void unionfs_post_opts();
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/string.c 
new/unionfs-fuse-0.25/src/string.c
--- old/unionfs-fuse-0.23/src/string.c  2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/string.c  2012-02-02 13:30:22.000000000 +0100
@@ -92,7 +92,7 @@
                return ret;
        }
 
-       char *ri = rindex(ret, '/'); 
+       char *ri = strrchr(ret, '/'); 
        if (ri != NULL) {
                *ri = '\0'; // '/' found, so a full path
        } else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/unionfs.c 
new/unionfs-fuse-0.25/src/unionfs.c
--- old/unionfs-fuse-0.23/src/unionfs.c 2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/unionfs.c 2012-02-02 13:30:22.000000000 +0100
@@ -2,7 +2,7 @@
 *
 * This is offered under a BSD-style license. This means you can use the code 
for whatever you
 * desire in any way you may want but you MUST NOT forget to give me 
appropriate credits when
-* spreading your work which is based on mine. Something like "original 
implementation by Radek 
+* spreading your work which is based on mine. Something like "original 
implementation by Radek
 * Podgorny" should be fine.
 *
 * License: BSD-style license
@@ -11,8 +11,8 @@
 */
 
 #ifdef linux
-       // For pread()/pwrite()
-       #define _XOPEN_SOURCE 500
+       // For pread()/pwrite()/utimensat()
+       #define _XOPEN_SOURCE 700
 #endif
 
 #include <fuse.h>
@@ -22,11 +22,16 @@
 #include <strings.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 #include <dirent.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/time.h>
-#include <sys/statvfs.h>
+#ifdef linux
+       #include <sys/vfs.h>
+#else
+       #include <sys/statvfs.h>
+#endif
 
 #ifdef HAVE_SETXATTR
        #include <sys/xattr.h>
@@ -50,10 +55,13 @@
        FUSE_OPT_KEY("--version", KEY_VERSION),
        FUSE_OPT_KEY("-h", KEY_HELP),
        FUSE_OPT_KEY("-V", KEY_VERSION),
+       FUSE_OPT_KEY("dirs=%s", KEY_DIRS),
        FUSE_OPT_KEY("stats", KEY_STATS),
        FUSE_OPT_KEY("cow", KEY_COW),
        FUSE_OPT_KEY("noinitgroups", KEY_NOINITGROUPS),
        FUSE_OPT_KEY("statfs_omit_ro", KEY_STATFS_OMIT_RO),
+       FUSE_OPT_KEY("chroot=%s,", KEY_CHROOT),
+       FUSE_OPT_KEY("max_files=%s", KEY_MAX_FILES),
        FUSE_OPT_END
 };
 
@@ -101,13 +109,15 @@
        char p[PATHLEN_MAX];
        snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path);
 
-       // NOTE: Create the file with mode=0 first, otherwise we might create
+       // NOTE: We should do:
+       //       Create the file with mode=0 first, otherwise we might create
        //       a file as root + x-bit + suid bit set, which might be used for
        //       security racing!
        int res = open(p, fi->flags, 0);
        if (res == -1) return -errno;
 
        set_owner(p); // no error check, since creating the file succeeded
+
        // NOW, that the file has the proper owner we may set the requested mode
        fchmod(res, mode);
 
@@ -118,8 +128,8 @@
 }
 
 
-/** 
- * flush may be called multiple times for an open file, this must not really 
+/**
+ * flush may be called multiple times for an open file, this must not really
  * close the file. This is important if used on a network filesystem like NFS
  * which flush the data/metadata on close()
  */
@@ -187,7 +197,7 @@
        int res = lstat(p, stbuf);
        if (res == -1) return -errno;
 
-       /* This is a workaround for broken gnu find implementations. Actually, 
+       /* This is a workaround for broken gnu find implementations. Actually,
         * n_links is not defined at all for directories by posix. However, it
         * seems to be common for filesystems to set it to one if the actual 
value
         * is unknown. Since nlink_t is unsigned and since these broken 
implementations
@@ -199,9 +209,30 @@
        return 0;
 }
 
+/**
+ * init method
+ * called before first access to the filesystem
+ */
+static void * unionfs_init(struct fuse_conn_info *conn) {
+       // just to prevent the compiler complaining about unused variables
+       (void) conn->max_readahead;
+
+       // we only now (from unionfs_init) may go into the chroot, since 
otherwise
+       // fuse_main() will fail to open /dev/fuse and to call mount
+       if (uopt.chroot) {
+               int res = chroot(uopt.chroot);
+               if (res) {
+                       usyslog("Chdir to %s failed: %s ! Aborting!\n",
+                                uopt.chroot, strerror(errno));
+                       exit(1);
+               }
+       }
+       return NULL;
+}
+
 static int unionfs_link(const char *from, const char *to) {
        DBG_IN();
-       
+
        // hardlinks do not work across different filesystems so we need a copy 
of from first
        int i = find_rw_branch_cow(from);
        if (i == -1) return -errno;
@@ -257,27 +288,29 @@
        char p[PATHLEN_MAX];
        snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path);
 
+       int file_type = mode & S_IFMT;
+       int file_perm = mode & (S_PROT_MASK);
+
        int res = -1;
-       if ((mode & S_IFMT) == S_IFREG) {
+       if ((file_type) == S_IFREG) {
                // under FreeBSD, only the super-user can create ordinary files 
using mknod
                // Actually this workaround should not be required any more
                // since we now have the unionfs_create() method
                // So can we remove it?
-               
+
                usyslog (LOG_INFO, "deprecated mknod workaround, tell the 
unionfs-fuse authors if you see this!\n");
-               
+
                res = creat(p, 0);
-               if (res > 0) 
-                       if (close (res) == -1) usyslog (LOG_WARNING, "Warning, 
cannot close file\n");
+               if (res > 0 && close(res) == -1) usyslog(LOG_WARNING, "Warning, 
cannot close file\n");
        } else {
-               res = mknod(p, 0, rdev);
+               res = mknod(p, file_type, rdev);
        }
 
        if (res == -1) return -errno;
-       
+
        set_owner(p); // no error check, since creating the file succeeded
        // NOW, that the file has the proper owner we may set the requested mode
-       chmod(p, mode);
+       chmod(p, file_perm);
 
        remove_hidden(path, i);
 
@@ -331,9 +364,9 @@
                char out[STATS_SIZE] = "";
                stats_sprint(&stats, out);
 
-               int s = size;
-               if (offset < strlen(out)) {
-                       if (s > strlen(out)-offset) s = strlen(out)-offset;
+               off_t s = size;
+               if (offset < (off_t) strlen(out)) {
+                       if (s > (off_t) strlen(out) - offset) s = 
strlen(out)-offset;
                        memcpy(buf, out+offset, s);
                } else {
                        s = 0;
@@ -382,12 +415,12 @@
 
 /**
  * unionfs rename function
- * TODO: If we rename a directory on a read-only branch, we need to copy over 
+ * TODO: If we rename a directory on a read-only branch, we need to copy over
  *       all files to the renamed directory on the read-write branch.
  */
 static int unionfs_rename(const char *from, const char *to) {
        DBG_IN();
-       
+
        bool is_dir = false; // is 'from' a file or directory
 
        int j = find_rw_branch_cutlast(to);
@@ -412,9 +445,9 @@
        snprintf(t, PATHLEN_MAX, "%s%s", uopt.branches[i].path, to);
 
        filetype_t ftype = path_is_dir(f);
-       if (ftype == NOT_EXISTING)  
+       if (ftype == NOT_EXISTING)
                return -ENOENT;
-       else if (ftype == IS_DIR) 
+       else if (ftype == IS_DIR)
                is_dir = true;
 
        int res;
@@ -437,7 +470,7 @@
                        if (unlink(f))
                                usyslog(LOG_ERR, "%s: cow of %s succeeded, but 
rename() failed and now "
                                       "also unlink()  failed\n", __func__, 
from);
-                       
+
                        if (remove_hidden(from, i))
                                usyslog(LOG_ERR, "%s: cow of %s succeeded, but 
rename() failed and now "
                                       "also removing the whiteout  failed\n", 
__func__, from);
@@ -459,6 +492,60 @@
        return 0;
 }
 
+/**
+ * Wrapper function to convert the result of statfs() to statvfs()
+ * libfuse uses statvfs, since it conforms to POSIX. Unfortunately,
+ * glibc's statvfs parses /proc/mounts, which then results in reading
+ * the filesystem itself again - which would result in a deadlock.
+ * TODO: BSD/MacOSX
+ */
+static int statvfs_local(const char *path, struct statvfs *stbuf) {
+#ifdef linux
+       /* glibc's statvfs walks /proc/mounts and stats entries found there
+        * in order to extract their mount flags, which may deadlock if they
+        * are mounted under the unionfs. As a result, we have to do this
+        * ourselves.
+        */
+       struct statfs stfs;
+       int res = statfs(path, &stfs);
+       if (res == -1) return res;
+
+       memset(stbuf, 0, sizeof(*stbuf));
+       stbuf->f_bsize = stfs.f_bsize;
+       if (stfs.f_frsize)
+               stbuf->f_frsize = stfs.f_frsize;
+       else
+               stbuf->f_frsize = stfs.f_bsize;
+       stbuf->f_blocks = stfs.f_blocks;
+       stbuf->f_bfree = stfs.f_bfree;
+       stbuf->f_bavail = stfs.f_bavail;
+       stbuf->f_files = stfs.f_files;
+       stbuf->f_ffree = stfs.f_ffree;
+       stbuf->f_favail = stfs.f_ffree; /* nobody knows */
+       stbuf->f_fsid = stfs.f_fsid.__val[0];
+
+       /* We don't worry about flags, exactly because this would
+        * require reading /proc/mounts, and avoiding that and the
+        * resulting deadlocks is exactly what we're trying to avoid
+        * by doing this rather than using statvfs.
+        */
+       stbuf->f_flag = 0;
+       stbuf->f_namemax = stfs.f_namelen;
+
+       return 0;
+#else
+       return statvfs(path, stbuf);
+#endif
+}
+
+
+
+/**
+ * statvs implementation
+ * TODO: fsid: It would be optimal, if we would store a once generated random
+ *            fsid. But what if the same branch with the fsid used for 
different 
+ *            unions? Is the present way ok for most cases?
+ */
 static int unionfs_statfs(const char *path, struct statvfs *stbuf) {
        (void)path;
 
@@ -471,7 +558,7 @@
        int i = 0;
        for (i = 0; i < uopt.nbranches; i++) {
                struct statvfs stb;
-               int res = statvfs(uopt.branches[i].path, &stb);
+               int res = statvfs_local(uopt.branches[i].path, &stb);
                if (res == -1) continue;
 
                struct stat st;
@@ -482,6 +569,7 @@
                if (first) {
                        memcpy(stbuf, &stb, sizeof(*stbuf));
                        first = 0;
+                       stbuf->f_fsid = stb.f_fsid << 8;
                        continue;
                }
 
@@ -504,21 +592,24 @@
                                stbuf->f_ffree += stb.f_ffree;
                                stbuf->f_favail += stb.f_favail;
                        } else if (!uopt.statfs_omit_ro) {
-                               // omitting the RO branches is not correct 
regarding the block counts but it actually fixes the percentage of free space. 
so, let the user decide.
-
+                               // omitting the RO branches is not correct 
regarding
+                               // the block counts but it actually fixes the 
+                               // percentage of free space. so, let the user 
decide.
                                stbuf->f_blocks += stb.f_blocks * ratio;
                                stbuf->f_files  += stb.f_files;
                        }
 
-                       if (!stb.f_flag & ST_RDONLY) stbuf->f_flag &= 
~ST_RDONLY;
-                       if (!stb.f_flag & ST_NOSUID) stbuf->f_flag &= 
~ST_NOSUID;
+                       if (!(stb.f_flag & ST_RDONLY)) stbuf->f_flag &= 
~ST_RDONLY;
+                       if (!(stb.f_flag & ST_NOSUID)) stbuf->f_flag &= 
~ST_NOSUID;
 
                        if (stb.f_namemax < stbuf->f_namemax) stbuf->f_namemax 
= stb.f_namemax;
+
+                       // we don't care about overflows, the fsid just should 
be different
+                       // from other fsids
+                       stbuf->f_fsid += stb.f_fsid;
                }
        }
 
-       stbuf->f_fsid = 0;
-
        return 0;
 }
 
@@ -567,13 +658,7 @@
        char p[PATHLEN_MAX];
        snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path);
 
-       struct timeval tv[2];
-        tv[0].tv_sec  = ts[0].tv_sec;
-        tv[0].tv_usec = ts[0].tv_nsec / 1000;
-        tv[1].tv_sec  = ts[1].tv_sec;
-        tv[1].tv_usec = ts[1].tv_nsec / 1000;
-
-       int res = utimes(p, tv);
+       int res = utimensat(0, p, ts, AT_SYMLINK_NOFOLLOW);
 
        if (res == -1) return -errno;
 
@@ -628,7 +713,7 @@
 
 static int unionfs_removexattr(const char *path, const char *name) {
        DBG_IN();
-       
+
        int i = find_rw_branch_cow(path);
        if (i == -1) return -errno;
 
@@ -654,7 +739,7 @@
        int res = lsetxattr(p, name, value, size, flags);
 
        if (res == -1) return -errno;
-       
+
        return res;
 }
 #endif // HAVE_SETXATTR
@@ -662,11 +747,12 @@
 static struct fuse_operations unionfs_oper = {
        .chmod  = unionfs_chmod,
        .chown  = unionfs_chown,
-       .create = unionfs_create,
+       .create         = unionfs_create,
        .flush  = unionfs_flush,
        .fsync  = unionfs_fsync,
        .getattr        = unionfs_getattr,
-       .link   = unionfs_link,
+       .init           = unionfs_init,
+       .link           = unionfs_link,
        .mkdir  = unionfs_mkdir,
        .mknod  = unionfs_mknod,
        .open   = unionfs_open,
@@ -683,10 +769,10 @@
        .utimens        = unionfs_utimens,
        .write  = unionfs_write,
 #ifdef HAVE_SETXATTR
-       .getxattr       = unionfs_getxattr,
-       .listxattr      = unionfs_listxattr,
+       .getxattr               = unionfs_getxattr,
+       .listxattr              = unionfs_listxattr,
        .removexattr    = unionfs_removexattr,
-       .setxattr       = unionfs_setxattr,
+       .setxattr               = unionfs_setxattr,
 #endif
 };
 
@@ -708,29 +794,15 @@
 
                if (uopt.stats_enabled) stats_init(&stats);
        }
-       
-       // enable fuse permission checks, we need to set this, even we we are 
+
+       // enable fuse permission checks, we need to set this, even we we are
        // not root, since we don't have our own access() function
        if (fuse_opt_add_arg(&args, "-odefault_permissions")) {
                fprintf(stderr, "Severe failure, can't enable permssion checks, 
aborting!\n");
                exit(1);
        }
+       unionfs_post_opts();
 
-        // Prevent accidental umounts. Especially system shutdown scripts tend 
-       // to umount everything they can. If we don't have an open file 
descriptor, 
-       // this might cause unexpected behaviour.
-        int i = 0;
-        for (i = 0; i < uopt.nbranches; i++) {
-               char *path = uopt.branches[i].path;
-               int fd = open(path, O_RDONLY);
-               if (fd == -1) {
-                       fprintf(stderr, "\nFailed to open %s: %s. 
Aborting!\n\n", 
-                               path, strerror(errno));
-                       exit(1);
-               }
-                uopt.branches[i].fd = fd;
-        }
-       
        umask(0);
        res = fuse_main(args.argc, args.argv, &unionfs_oper, NULL);
        return uopt.doexit ? uopt.retval : res;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/unionfs.h 
new/unionfs-fuse-0.25/src/unionfs.h
--- old/unionfs-fuse-0.23/src/unionfs.h 2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/unionfs.h 2012-02-02 13:30:22.000000000 +0100
@@ -11,10 +11,13 @@
 #define HIDETAG "_HIDDEN~"
 #define METADIR ".unionfs/"
 
+// file access protection mask
+#define S_PROT_MASK (S_ISUID| S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+
 typedef struct {
        char *path;
-       int fd; // used to prevent accidental umounts of path
-       unsigned char rw; // the writable flag
+       int fd;                  // used to prevent accidental umounts of path
+       unsigned char rw;        // the writable flag
 } branch_entry_t;
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/src/version.h 
new/unionfs-fuse-0.25/src/version.h
--- old/unionfs-fuse-0.23/src/version.h 2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/src/version.h 2012-02-02 13:30:22.000000000 +0100
@@ -4,5 +4,5 @@
 */
 
 #ifndef _VERSION_H
-#define VERSION "0.23"
+#define VERSION "0.25"
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unionfs-fuse-0.23/test.sh 
new/unionfs-fuse-0.25/test.sh
--- old/unionfs-fuse-0.23/test.sh       2009-03-22 19:58:01.000000000 +0100
+++ new/unionfs-fuse-0.25/test.sh       2012-02-02 13:30:22.000000000 +0100
@@ -7,7 +7,7 @@
 echo v1 > original/play-with-me
 echo v1 > original/delete-me
 
-./unionfs -o cow working-copy=rw:original=ro base
+src/unionfs -o cow working-copy=rw:original=ro base
 trap 'if [ "$(ls base)" ]; then umount base; fi; rm -rf base original 
working-copy' EXIT
 sleep 1
 

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to