Hello community,

here is the log from the commit of package s3backer for openSUSE:Factory 
checked in at 2013-06-05 13:38:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/s3backer (Old)
 and      /work/SRC/openSUSE:Factory/.s3backer.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "s3backer"

Changes:
--------
--- /work/SRC/openSUSE:Factory/s3backer/s3backer.changes        2013-04-03 
13:06:23.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.s3backer.new/s3backer.changes   2013-06-05 
14:24:47.000000000 +0200
@@ -1,0 +2,7 @@
+Wed May 29 17:49:29 UTC 2013 - [email protected]
+
+- Update to version 1.3.5
+  + Check for duplicate mount at startup (issue #10)
+  + Minor spec file cleanups
+
+-------------------------------------------------------------------

Old:
----
  s3backer-1.3.4.tar.gz

New:
----
  s3backer-1.3.5.tar.gz

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

Other differences:
------------------
++++++ s3backer.spec ++++++
--- /var/tmp/diff_new_pack.mdgd2q/_old  2013-06-05 14:24:47.000000000 +0200
+++ /var/tmp/diff_new_pack.mdgd2q/_new  2013-06-05 14:24:47.000000000 +0200
@@ -18,7 +18,7 @@
 
 
 Name:           s3backer
-Version:        1.3.4
+Version:        1.3.5
 Release:        0
 Summary:        FUSE-based single file backing store via Amazon S3
 License:        GPL-2.0+
@@ -61,22 +61,17 @@
 %build
 export SUSE_ASNEEDED=0
 %{configure}
-make
+make %{?_smp_mflags}
 
 %install
-rm -rf ${RPM_BUILD_ROOT}
-%{makeinstall}
-install COPYING %{buildroot}%{_datadir}/doc/packages/%{name}/
-rm -f %{buildroot}%{_datadir}/doc/packages/%{name}/INSTALL
+make install DESTDIR='%{buildroot}'
+install -m 0644 COPYING %{buildroot}%{_docdir}/%{name}/
+rm -f %{buildroot}%{_docdir}/%{name}/INSTALL
 
 %files
-%defattr(0644,root,root,0755)
-%attr(0755,root,root) %{_bindir}/%{name}
-%if 0%{?mandriva_version}
-%attr(0644,root,root) %{_mandir}/man1/%{name}.1
-%else
-%attr(0644,root,root) %{_mandir}/man1/%{name}.1.gz
-%endif
-%doc %{_datadir}/doc/packages/%{name}
+%defattr(-,root,root,-)
+%{_bindir}/*
+%{_mandir}/man1/*
+%{_docdir}/%{name}
 
 %changelog

++++++ s3backer-1.3.4.tar.gz -> s3backer-1.3.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/CHANGES new/s3backer-1.3.5/CHANGES
--- old/s3backer-1.3.4/CHANGES  2013-04-03 03:44:48.000000000 +0200
+++ new/s3backer-1.3.5/CHANGES  2013-05-29 19:43:01.000000000 +0200
@@ -1,3 +1,7 @@
+Version 1.3.5 (r485) released 29 May 2013
+
+    - Check for duplicate mount at startup (issue #10)
+    - Remove obsolete backward-compatibility block size check
 
 Version 1.3.4 (r476) released 2 Apr 2013
 
@@ -134,4 +138,4 @@
 
 Version 1.0.0 released 19 June 2008
 
-$Id: CHANGES 476 2013-04-03 01:44:44Z archie.cobbs $
+$Id: CHANGES 485 2013-05-29 17:42:59Z archie.cobbs $
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/Makefile.am 
new/s3backer-1.3.5/Makefile.am
--- old/s3backer-1.3.4/Makefile.am      2011-02-01 18:31:15.000000000 +0100
+++ new/s3backer-1.3.5/Makefile.am      2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301, USA.
 #
-# $Id: Makefile.am 448 2011-02-01 17:31:15Z archie.cobbs $
+# $Id: Makefile.am 482 2013-05-11 17:07:49Z archie.cobbs $
 #
 
 bin_PROGRAMS=       s3backer
@@ -35,6 +35,7 @@
                        fuse_ops.h \
                        hash.h \
                        http_io.h \
+                       reset.h \
                        test_io.h \
                        s3b_config.h
 
@@ -55,6 +56,7 @@
                    fuse_ops.c \
                    hash.c \
                    http_io.c \
+                   reset.c \
                    s3b_config.c \
                    test_io.c \
                    svnrev.c
@@ -67,6 +69,7 @@
                    erase.c \
                    hash.c \
                    http_io.c \
+                   reset.c \
                    s3b_config.c \
                    test_io.c \
                    svnrev.c
@@ -76,5 +79,5 @@
 SUBDIRS=            debian
 
 svnrev.c:
-                       printf 'const int s3backer_svnrev = %u;\n' `svn info | 
grep -w Rev | sed -r 's/^.*Rev: //g'` > svnrev.c
+                       printf 'const int s3backer_svnrev = %u;\n' `svn info | 
grep -w Rev | sed 's/^.*Rev: //g'` > svnrev.c
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/Makefile.in 
new/s3backer-1.3.5/Makefile.in
--- old/s3backer-1.3.4/Makefile.in      2013-04-03 03:45:21.000000000 +0200
+++ new/s3backer-1.3.5/Makefile.in      2013-05-29 19:43:26.000000000 +0200
@@ -34,7 +34,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301, USA.
 #
-# $Id: Makefile.am 448 2011-02-01 17:31:15Z archie.cobbs $
+# $Id: Makefile.am 482 2013-05-11 17:07:49Z archie.cobbs $
 #
 
 
@@ -99,14 +99,15 @@
 am_s3backer_OBJECTS = main.$(OBJEXT) block_cache.$(OBJEXT) \
        block_part.$(OBJEXT) dcache.$(OBJEXT) ec_protect.$(OBJEXT) \
        erase.$(OBJEXT) fuse_ops.$(OBJEXT) hash.$(OBJEXT) \
-       http_io.$(OBJEXT) s3b_config.$(OBJEXT) test_io.$(OBJEXT) \
-       svnrev.$(OBJEXT)
+       http_io.$(OBJEXT) reset.$(OBJEXT) s3b_config.$(OBJEXT) \
+       test_io.$(OBJEXT) svnrev.$(OBJEXT)
 s3backer_OBJECTS = $(am_s3backer_OBJECTS)
 s3backer_LDADD = $(LDADD)
 am_tester_OBJECTS = tester.$(OBJEXT) block_cache.$(OBJEXT) \
        block_part.$(OBJEXT) dcache.$(OBJEXT) ec_protect.$(OBJEXT) \
        erase.$(OBJEXT) hash.$(OBJEXT) http_io.$(OBJEXT) \
-       s3b_config.$(OBJEXT) test_io.$(OBJEXT) svnrev.$(OBJEXT)
+       reset.$(OBJEXT) s3b_config.$(OBJEXT) test_io.$(OBJEXT) \
+       svnrev.$(OBJEXT)
 tester_OBJECTS = $(am_tester_OBJECTS)
 tester_LDADD = $(LDADD)
 DEFAULT_INCLUDES = -I.@am__isrc@
@@ -314,6 +315,7 @@
                        fuse_ops.h \
                        hash.h \
                        http_io.h \
+                       reset.h \
                        test_io.h \
                        s3b_config.h
 
@@ -329,6 +331,7 @@
                    fuse_ops.c \
                    hash.c \
                    http_io.c \
+                   reset.c \
                    s3b_config.c \
                    test_io.c \
                    svnrev.c
@@ -341,6 +344,7 @@
                    erase.c \
                    hash.c \
                    http_io.c \
+                   reset.c \
                    s3b_config.c \
                    test_io.c \
                    svnrev.c
@@ -468,6 +472,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_io.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reset.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s3b_config.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svnrev.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_io.Po@am__quote@
@@ -1047,7 +1052,7 @@
 
 
 svnrev.c:
-                       printf 'const int s3backer_svnrev = %u;\n' `svn info | 
grep -w Rev | sed -r 's/^.*Rev: //g'` > svnrev.c
+                       printf 'const int s3backer_svnrev = %u;\n' `svn info | 
grep -w Rev | sed 's/^.*Rev: //g'` > svnrev.c
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/block_cache.c 
new/s3backer-1.3.5/block_cache.c
--- old/s3backer-1.3.4/block_cache.c    2011-02-01 18:31:15.000000000 +0100
+++ new/s3backer-1.3.5/block_cache.c    2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: block_cache.c 448 2011-02-01 17:31:15Z archie.cobbs $
+ * $Id: block_cache.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -169,6 +169,8 @@
 };
 
 /* s3backer_store functions */
+static int block_cache_meta_data(struct s3backer_store *s3b, off_t 
*file_sizep, u_int *block_sizep);
+static int block_cache_set_mounted(struct s3backer_store *s3b, int 
*old_valuep, int new_value);
 static int block_cache_read_block(struct s3backer_store *s3b, s3b_block_t 
block_num, void *dest,
   u_char *actual_md5, const u_char *expect_md5, int strict);
 static int block_cache_write_block(struct s3backer_store *s3b, s3b_block_t 
block_num, const void *src, u_char *md5,
@@ -176,6 +178,7 @@
 static int block_cache_read_block_part(struct s3backer_store *s3b, s3b_block_t 
block_num, u_int off, u_int len, void *dest);
 static int block_cache_write_block_part(struct s3backer_store *s3b, 
s3b_block_t block_num, u_int off, u_int len, const void *src);
 static int block_cache_list_blocks(struct s3backer_store *s3b, 
block_list_func_t *callback, void *arg);
+static int block_cache_flush(struct s3backer_store *s3b);
 static void block_cache_destroy(struct s3backer_store *s3b);
 
 /* Other functions */
@@ -228,11 +231,14 @@
         (*config->log)(LOG_ERR, "calloc(): %s", strerror(r));
         goto fail0;
     }
+    s3b->meta_data = block_cache_meta_data;
+    s3b->set_mounted = block_cache_set_mounted;
     s3b->read_block = block_cache_read_block;
     s3b->write_block = block_cache_write_block;
     s3b->read_block_part = block_cache_read_block_part;
     s3b->write_block_part = block_cache_write_block_part;
     s3b->list_blocks = block_cache_list_blocks;
+    s3b->flush = block_cache_flush;
     s3b->destroy = block_cache_destroy;
 
     /* Initialize block_cache_private structure */
@@ -370,9 +376,43 @@
     return 0;
 }
 
-/*
- * Destructor
- */
+static int
+block_cache_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int 
*block_sizep)
+{
+    struct block_cache_private *const priv = s3b->data;
+
+    return (*priv->inner->meta_data)(priv->inner, file_sizep, block_sizep);
+}
+
+static int
+block_cache_set_mounted(struct s3backer_store *s3b, int *old_valuep, int 
new_value)
+{
+    struct block_cache_private *const priv = s3b->data;
+
+    return (*priv->inner->set_mounted)(priv->inner, old_valuep, new_value);
+}
+
+static int
+block_cache_flush(struct s3backer_store *const s3b)
+{
+    struct block_cache_private *const priv = s3b->data;
+
+    /* Grab lock and sanity check */
+    pthread_mutex_lock(&priv->mutex);
+    S3BCACHE_CHECK_INVARIANTS(priv);
+
+    /* Wait for all dirty blocks to be written and all worker threads to exit 
*/
+    priv->stopping = 1;
+    while (TAILQ_FIRST(&priv->dirties) != NULL || priv->num_threads > 0) {
+        pthread_cond_broadcast(&priv->worker_work);
+        pthread_cond_wait(&priv->worker_exit, &priv->mutex);
+    }
+
+    /* Release lock */
+    pthread_mutex_unlock(&priv->mutex);
+    return 0;
+}
+
 static void
 block_cache_destroy(struct s3backer_store *const s3b)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/configure new/s3backer-1.3.5/configure
--- old/s3backer-1.3.4/configure        2013-04-03 03:45:22.000000000 +0200
+++ new/s3backer-1.3.5/configure        2013-05-29 19:43:26.000000000 +0200
@@ -1,7 +1,7 @@
 #! /bin/sh
-# From configure.ac Id: configure.ac 470 2013-03-04 18:31:13Z archie.cobbs .
+# From configure.ac Id: configure.ac 477 2013-04-03 01:57:08Z archie.cobbs .
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for s3backer FUSE filesystem backed by Amazon 
S3 1.3.4.
+# Generated by GNU Autoconf 2.69 for s3backer FUSE filesystem backed by Amazon 
S3 1.3.5.
 #
 # Report bugs to <http://s3backer.googlecode.com/>.
 #
@@ -581,8 +581,8 @@
 # Identity of this package.
 PACKAGE_NAME='s3backer FUSE filesystem backed by Amazon S3'
 PACKAGE_TARNAME='s3backer'
-PACKAGE_VERSION='1.3.4'
-PACKAGE_STRING='s3backer FUSE filesystem backed by Amazon S3 1.3.4'
+PACKAGE_VERSION='1.3.5'
+PACKAGE_STRING='s3backer FUSE filesystem backed by Amazon S3 1.3.5'
 PACKAGE_BUGREPORT='http://s3backer.googlecode.com/'
 PACKAGE_URL=''
 
@@ -1275,7 +1275,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 s3backer FUSE filesystem backed by Amazon S3 1.3.4 to 
adapt to many kinds of systems.
+\`configure' configures s3backer FUSE filesystem backed by Amazon S3 1.3.5 to 
adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1341,7 +1341,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of s3backer FUSE filesystem 
backed by Amazon S3 1.3.4:";;
+     short | recursive ) echo "Configuration of s3backer FUSE filesystem 
backed by Amazon S3 1.3.5:";;
    esac
   cat <<\_ACEOF
 
@@ -1440,7 +1440,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-s3backer FUSE filesystem backed by Amazon S3 configure 1.3.4
+s3backer FUSE filesystem backed by Amazon S3 configure 1.3.5
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1788,7 +1788,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by s3backer FUSE filesystem backed by Amazon S3 $as_me 1.3.4, 
which was
+It was created by s3backer FUSE filesystem backed by Amazon S3 $as_me 1.3.5, 
which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2612,7 +2612,7 @@
 
 # Define the identity of the package.
  PACKAGE='s3backer'
- VERSION='1.3.4'
+ VERSION='1.3.5'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -5335,7 +5335,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by s3backer FUSE filesystem backed by Amazon S3 $as_me 
1.3.4, which was
+This file was extended by s3backer FUSE filesystem backed by Amazon S3 $as_me 
1.3.5, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -5401,7 +5401,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-s3backer FUSE filesystem backed by Amazon S3 config.status 1.3.4
+s3backer FUSE filesystem backed by Amazon S3 config.status 1.3.5
 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/s3backer-1.3.4/configure.ac 
new/s3backer-1.3.5/configure.ac
--- old/s3backer-1.3.4/configure.ac     2013-03-04 19:31:21.000000000 +0100
+++ new/s3backer-1.3.5/configure.ac     2013-04-03 03:57:11.000000000 +0200
@@ -18,15 +18,15 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301, USA.
 #
-# $Id: configure.ac 470 2013-03-04 18:31:13Z archie.cobbs $
+# $Id: configure.ac 477 2013-04-03 01:57:08Z archie.cobbs $
 #
 
-AC_INIT([s3backer FUSE filesystem backed by Amazon S3], [1.3.4], 
[http://s3backer.googlecode.com/], [s3backer])
+AC_INIT([s3backer FUSE filesystem backed by Amazon S3], [1.3.5], 
[http://s3backer.googlecode.com/], [s3backer])
 AC_CONFIG_AUX_DIR(scripts)
 AM_INIT_AUTOMAKE
 dnl AM_MAINTAINER_MODE
 AC_PREREQ(2.59)
-AC_REVISION($Id: configure.ac 470 2013-03-04 18:31:13Z archie.cobbs $)
+AC_REVISION($Id: configure.ac 477 2013-04-03 01:57:08Z archie.cobbs $)
 AC_PREFIX_DEFAULT(/usr)
 AC_PROG_MAKE_SET
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/ec_protect.c 
new/s3backer-1.3.5/ec_protect.c
--- old/s3backer-1.3.4/ec_protect.c     2011-02-01 18:31:15.000000000 +0100
+++ new/s3backer-1.3.5/ec_protect.c     2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: ec_protect.c 448 2011-02-01 17:31:15Z archie.cobbs $
+ * $Id: ec_protect.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -113,12 +113,15 @@
 };
 
 /* s3backer_store functions */
+static int ec_protect_meta_data(struct s3backer_store *s3b, off_t *file_sizep, 
u_int *block_sizep);
+static int ec_protect_set_mounted(struct s3backer_store *s3b, int *old_valuep, 
int new_value);
 static int ec_protect_read_block(struct s3backer_store *s3b, s3b_block_t 
block_num, void *dest,
   u_char *actual_md5, const u_char *expect_md5, int strict);
 static int ec_protect_write_block(struct s3backer_store *s3b, s3b_block_t 
block_num, const void *src, u_char *md5,
   check_cancel_t *check_cancel, void *check_cancel_arg);
 static int ec_protect_read_block_part(struct s3backer_store *s3b, s3b_block_t 
block_num, u_int off, u_int len, void *dest);
 static int ec_protect_write_block_part(struct s3backer_store *s3b, s3b_block_t 
block_num, u_int off, u_int len, const void *src);
+static int ec_protect_flush(struct s3backer_store *s3b);
 static void ec_protect_destroy(struct s3backer_store *s3b);
 
 /* Misc */
@@ -160,11 +163,14 @@
         (*config->log)(LOG_ERR, "calloc(): %s", strerror(r));
         goto fail0;
     }
+    s3b->meta_data = ec_protect_meta_data;
+    s3b->set_mounted = ec_protect_set_mounted;
     s3b->read_block = ec_protect_read_block;
     s3b->write_block = ec_protect_write_block;
     s3b->read_block_part = ec_protect_read_block_part;
     s3b->write_block_part = ec_protect_write_block_part;
     s3b->list_blocks = ec_protect_list_blocks;
+    s3b->flush = ec_protect_flush;
     s3b->destroy = ec_protect_destroy;
     if ((priv = calloc(1, sizeof(*priv))) == NULL) {
         r = errno;
@@ -208,9 +214,40 @@
     return NULL;
 }
 
-/*
- * Destructor
- */
+static int
+ec_protect_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int 
*block_sizep)
+{
+    struct ec_protect_private *const priv = s3b->data;
+
+    return (*priv->inner->meta_data)(priv->inner, file_sizep, block_sizep);
+}
+
+static int
+ec_protect_set_mounted(struct s3backer_store *s3b, int *old_valuep, int 
new_value)
+{
+    struct ec_protect_private *const priv = s3b->data;
+
+    return (*priv->inner->set_mounted)(priv->inner, old_valuep, new_value);
+}
+
+static int
+ec_protect_flush(struct s3backer_store *const s3b)
+{
+    struct ec_protect_private *const priv = s3b->data;
+
+    /* Grab lock and sanity check */
+    pthread_mutex_lock(&priv->mutex);
+    EC_PROTECT_CHECK_INVARIANTS(priv);
+
+    /* Wait for all sleeping writers to finish */
+    while (priv->num_sleepers > 0)
+        pthread_cond_wait(&priv->sleepers_cond, &priv->mutex);
+
+    /* Release lock */
+    pthread_mutex_unlock(&priv->mutex);
+    return 0;
+}
+
 static void
 ec_protect_destroy(struct s3backer_store *const s3b)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/erase.c new/s3backer-1.3.5/erase.c
--- old/s3backer-1.3.4/erase.c  2011-02-01 18:31:15.000000000 +0100
+++ new/s3backer-1.3.5/erase.c  2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: erase.c 448 2011-02-01 17:31:15Z archie.cobbs $
+ * $Id: erase.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -115,6 +115,12 @@
         goto fail3;
     }
 
+    /* Clear mounted flag */
+    if ((r = (*priv->s3b->set_mounted)(priv->s3b, NULL, 1)) != 0) {
+        warnx("can't clear mounted flag: %s", strerror(r));
+        goto fail3;
+    }
+
     /* Success */
     ok = 1;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/fuse_ops.c 
new/s3backer-1.3.5/fuse_ops.c
--- old/s3backer-1.3.4/fuse_ops.c       2013-03-04 19:31:21.000000000 +0100
+++ new/s3backer-1.3.5/fuse_ops.c       2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: fuse_ops.c 470 2013-03-04 18:31:13Z archie.cobbs $
+ * $Id: fuse_ops.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -139,6 +139,7 @@
 static void *
 fuse_op_init(struct fuse_conn_info *conn)
 {
+    struct s3b_config *const s3bconf = config->s3bconf;
     struct fuse_ops_private *priv;
 
     /* Create private structure */
@@ -154,13 +155,14 @@
     priv->file_size = config->num_blocks * config->block_size;
 
     /* Create backing store */
-    if ((priv->s3b = s3backer_create_store(config->s3bconf)) == NULL) {
+    if ((priv->s3b = s3backer_create_store(s3bconf)) == NULL) {
         (*config->log)(LOG_ERR, "fuse_op_init(): can't create s3backer_store: 
%s", strerror(errno));
         free(priv);
         return NULL;
     }
 
     /* Done */
+    (*config->log)(LOG_INFO, "mounting %s", s3bconf->mount);
     return priv;
 }
 
@@ -168,11 +170,33 @@
 fuse_op_destroy(void *data)
 {
     struct fuse_ops_private *const priv = data;
+    struct s3backer_store *const s3b = priv->s3b;
+    struct s3b_config *const s3bconf = config->s3bconf;
+    int r;
+
+    /* Sanity check */
+    if (priv == NULL)
+        return;
+    (*config->log)(LOG_INFO, "unmount %s: initiated", s3bconf->mount);
+
+    /* Flush dirty data */
+    if (!config->read_only) {
+        (*config->log)(LOG_INFO, "unmount %s: flushing dirty data", 
s3bconf->mount);
+        if ((r = (*s3b->flush)(s3b)) != 0)
+            (*config->log)(LOG_ERR, "unmount %s: flushing filesystem failed: 
%s", s3bconf->mount, strerror(r));
+    }
 
-    if (priv != NULL) {
-        (*priv->s3b->destroy)(priv->s3b);
-        free(priv);
+    /* Clear mounted flag */
+    if (!config->read_only) {
+        (*config->log)(LOG_INFO, "unmount %s: clearing mounted flag", 
s3bconf->mount);
+        if ((r = (*s3b->set_mounted)(s3b, NULL, 0)) != 0)
+            (*config->log)(LOG_ERR, "unmount %s: clearing mounted flag failed: 
%s", s3bconf->mount, strerror(r));
     }
+
+    /* Shutdown */
+    (*s3b->destroy)(s3b);
+    (*config->log)(LOG_INFO, "unmount %s: completed", s3bconf->mount);
+    free(priv);
 }
 
 static int
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/http_io.c new/s3backer-1.3.5/http_io.c
--- old/s3backer-1.3.4/http_io.c        2013-03-04 19:33:15.000000000 +0100
+++ new/s3backer-1.3.5/http_io.c        2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: http_io.c 471 2013-03-04 18:33:11Z archie.cobbs $
+ * $Id: http_io.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -57,6 +57,12 @@
 /* MIME type for blocks */
 #define CONTENT_TYPE                "application/x-s3backer-block"
 
+/* MIME type for mounted flag */
+#define MOUNTED_FLAG_CONTENT_TYPE   "text/plain"
+
+/* Mounted file object name */
+#define MOUNTED_FLAG                "s3backer-mounted"
+
 /* HTTP `Date' header format */
 #define DATE_BUF_SIZE               64
 #define DATE_BUF_FMT                "%a, %d %b %Y %H:%M:%S GMT"
@@ -166,6 +172,8 @@
 typedef void http_io_curl_prepper_t(CURL *curl, struct http_io *io);
 
 /* s3backer_store functions */
+static int http_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, 
u_int *block_sizep);
+static int http_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, 
int new_value);
 static int http_io_read_block(struct s3backer_store *s3b, s3b_block_t 
block_num, void *dest,
   u_char *actual_md5, const u_char *expect_md5, int strict);
 static int http_io_write_block(struct s3backer_store *s3b, s3b_block_t 
block_num, const void *src, u_char *md5,
@@ -173,16 +181,18 @@
 static int http_io_read_block_part(struct s3backer_store *s3b, s3b_block_t 
block_num, u_int off, u_int len, void *dest);
 static int http_io_write_block_part(struct s3backer_store *s3b, s3b_block_t 
block_num, u_int off, u_int len, const void *src);
 static int http_io_list_blocks(struct s3backer_store *s3b, block_list_func_t 
*callback, void *arg);
+static int http_io_flush(struct s3backer_store *s3b);
 static void http_io_destroy(struct s3backer_store *s3b);
 
 /* Other functions */
-static http_io_curl_prepper_t http_io_detect_prepper;
+static http_io_curl_prepper_t http_io_head_prepper;
 static http_io_curl_prepper_t http_io_read_prepper;
 static http_io_curl_prepper_t http_io_write_prepper;
 static http_io_curl_prepper_t http_io_list_prepper;
 
 /* S3 REST API functions */
 static char *http_io_get_url(char *buf, size_t bufsiz, struct http_io_conf 
*config, s3b_block_t block_num);
+static char *http_io_get_mounted_flag(char *buf, size_t bufsiz, struct 
http_io_conf *config);
 static void http_io_get_auth(char *buf, size_t bufsiz, struct http_io_conf 
*config, const char *method,
     const char *ctype, const char *md5, const char *date, const struct 
curl_slist *headers, const char *resource);
 
@@ -244,11 +254,14 @@
         r = errno;
         goto fail0;
     }
+    s3b->meta_data = http_io_meta_data;
+    s3b->set_mounted = http_io_set_mounted;
     s3b->read_block = http_io_read_block;
     s3b->write_block = http_io_write_block;
     s3b->read_block_part = http_io_read_block_part;
     s3b->write_block_part = http_io_write_block_part;
     s3b->list_blocks = http_io_list_blocks;
+    s3b->flush = http_io_flush;
     s3b->destroy = http_io_destroy;
     if ((priv = calloc(1, sizeof(*priv))) == NULL) {
         r = errno;
@@ -374,6 +387,12 @@
     free(s3b);
 }
 
+static int
+http_io_flush(struct s3backer_store *const s3b)
+{
+    return 0;
+}
+
 void
 http_io_get_stats(struct s3backer_store *s3b, struct http_io_stats *stats)
 {
@@ -626,24 +645,13 @@
     return 0;
 }
 
-/*
- * Auto-detect block size and total size based on the first block.
- *
- * Returns:
- *
- *  0       Success
- *  ENOENT  Block not found
- *  ENXIO   Response was missing one of the two required headers
- *  Other   Other error
- */
-int
-http_io_detect_sizes(struct s3backer_store *s3b, off_t *file_sizep, u_int 
*block_sizep)
+static int
+http_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int 
*block_sizep)
 {
     struct http_io_private *const priv = s3b->data;
     struct http_io_conf *const config = priv->config;
     char urlbuf[URL_BUF_SIZE(config)];
     const char *resource;
-    u_int content_len;
     char authbuf[200];
     struct http_io io;
     char datebuf[64];
@@ -653,7 +661,6 @@
     memset(&io, 0, sizeof(io));
     io.url = urlbuf;
     io.method = HTTP_HEAD;
-    io.content_lengthp = &content_len;
 
     /* Construct URL for the first block */
     resource = http_io_get_url(urlbuf, sizeof(urlbuf), config, 0);
@@ -669,21 +676,16 @@
     }
 
     /* Perform operation */
-    if ((r = http_io_perform_io(priv, &io, http_io_detect_prepper)) != 0)
+    if ((r = http_io_perform_io(priv, &io, http_io_head_prepper)) != 0)
         goto done;
 
     /* Extract filesystem sizing information */
-    if (io.file_size == 0) {
-        r = ENXIO;
+    if (io.file_size == 0 || io.block_size == 0) {
+        r = ENOENT;
         goto done;
     }
     *file_sizep = (off_t)io.file_size;
-    if (io.block_size != 0)
-        *block_sizep = io.block_size;
-    else if (content_len != 0)
-        *block_sizep = content_len;         /* backward compatible */
-    else
-        r = ENXIO;
+    *block_sizep = io.block_size;
 
 done:
     /*  Clean up */
@@ -692,7 +694,7 @@
 }
 
 static void
-http_io_detect_prepper(CURL *curl, struct http_io *io)
+http_io_head_prepper(CURL *curl, struct http_io *io)
 {
     memset(&io->bufs, 0, sizeof(io->bufs));
     curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
@@ -704,6 +706,116 @@
 }
 
 static int
+http_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value)
+{
+    struct http_io_private *const priv = s3b->data;
+    struct http_io_conf *const config = priv->config;
+    char urlbuf[URL_BUF_SIZE(config) + sizeof(MOUNTED_FLAG)];
+    const char *resource;
+    char authbuf[200];
+    struct http_io io;
+    char datebuf[64];
+    int r = 0;
+
+    /* Initialize I/O info */
+    memset(&io, 0, sizeof(io));
+    io.url = urlbuf;
+    io.method = HTTP_HEAD;
+
+    /* Construct URL for the mounted flag */
+    resource = http_io_get_mounted_flag(urlbuf, sizeof(urlbuf), config);
+
+    /* Get old value */
+    if (old_valuep != NULL) {
+
+        /* Add Date header */
+        http_io_get_date(datebuf, sizeof(datebuf));
+        io.headers = http_io_add_header(io.headers, "%s: %s", DATE_HEADER, 
datebuf);
+
+        /* Add Authorization header */
+        if (config->accessId != NULL) {
+            http_io_get_auth(authbuf, sizeof(authbuf), config, io.method, 
NULL, NULL, datebuf, io.headers, resource);
+            io.headers = http_io_add_header(io.headers, "%s: AWS %s:%s", 
AUTH_HEADER, config->accessId, authbuf);
+        }
+
+        /* See if object exists */
+        switch ((r = http_io_perform_io(priv, &io, http_io_head_prepper))) {
+        case ENOENT:
+            *old_valuep = 0;
+            r = 0;
+            break;
+        case 0:
+            *old_valuep = 1;
+            break;
+        default:
+            goto done;
+        }
+    }
+
+    /* Set new value */
+    if (new_value != -1) {
+        u_char md5[MD5_DIGEST_LENGTH];
+        char md5buf[MD5_DIGEST_LENGTH * 2 + 1];
+        char content[HOST_NAME_MAX + 64];
+        MD5_CTX ctx;
+
+        /* Reset I/O info */
+        curl_slist_free_all(io.headers);
+        memset(&io, 0, sizeof(io));
+        io.url = urlbuf;
+        io.method = new_value ? HTTP_PUT : HTTP_DELETE;
+
+        /* Add Date header */
+        http_io_get_date(datebuf, sizeof(datebuf));
+        io.headers = http_io_add_header(io.headers, "%s: %s", DATE_HEADER, 
datebuf);
+
+        /* To set the flag PUT some content containing current date */
+        if (new_value) {
+
+            /* Create content for the mounted flag object */
+            snprintf(content, sizeof(content), "%s\n", datebuf);
+            io.src = content;
+            io.buf_size = strlen(content);
+            MD5_Init(&ctx);
+            MD5_Update(&ctx, content, strlen(content));
+            MD5_Final(md5, &ctx);
+
+            /* Add Content-Type header */
+            io.headers = http_io_add_header(io.headers, "%s: %s", 
CTYPE_HEADER, MOUNTED_FLAG_CONTENT_TYPE);
+
+            /* Add Content-MD5 header */
+            http_io_base64_encode(md5buf, sizeof(md5buf), md5, 
MD5_DIGEST_LENGTH);
+            io.headers = http_io_add_header(io.headers, "%s: %s", MD5_HEADER, 
md5buf);
+        }
+
+    /**** NOTE: we add the following "x-amz" headers in lexicographic order as 
required by http_io_get_auth() ****/
+
+        /* Add ACL header (PUT only) */
+        if (new_value)
+            io.headers = http_io_add_header(io.headers, "%s: %s", ACL_HEADER, 
config->accessType);
+
+        /* Add storage class header (if needed) */
+        if (config->rrs)
+            io.headers = http_io_add_header(io.headers, "%s: %s", 
STORAGE_CLASS_HEADER, SCLASS_REDUCED_REDUNDANCY);
+
+        /* Add Authorization header */
+        if (config->accessId != NULL) {
+            http_io_get_auth(authbuf, sizeof(authbuf), config, io.method,
+              new_value ? MOUNTED_FLAG_CONTENT_TYPE : NULL, new_value ? md5buf 
: NULL, datebuf, io.headers, resource);
+            io.headers = http_io_add_header(io.headers, "%s: AWS %s:%s", 
AUTH_HEADER, config->accessId, authbuf);
+        }
+
+        /* Perform operation to set or clear mounted flag */
+        r = http_io_perform_io(priv, &io, http_io_write_prepper);
+    }
+
+done:
+    /*  Clean up */
+    curl_slist_free_all(io.headers);
+    return r;
+}
+
+static int
 http_io_read_block(struct s3backer_store *const s3b, s3b_block_t block_num, 
void *dest,
   u_char *actual_md5, const u_char *expect_md5, int strict)
 {
@@ -1566,6 +1678,27 @@
         resource = buf + strlen(config->baseURL) + strlen(config->bucket);
     }
     (void)len;                  /* avoid compiler warning when NDEBUG defined 
*/
+    assert(len < bufsiz);
+    return resource;
+}
+
+/*
+ * Create URL for the mounted flag, and return pointer to the URL's path not 
including any "/bucket" prefix.
+ */
+static char *
+http_io_get_mounted_flag(char *buf, size_t bufsiz, struct http_io_conf *config)
+{
+    char *resource;
+    int len;
+
+    if (config->vhost) {
+        len = snprintf(buf, bufsiz, "%s%s%s", config->baseURL, config->prefix, 
MOUNTED_FLAG);
+        resource = buf + strlen(config->baseURL) - 1;
+    } else {
+        len = snprintf(buf, bufsiz, "%s%s/%s%s", config->baseURL, 
config->bucket, config->prefix, MOUNTED_FLAG);
+        resource = buf + strlen(config->baseURL) + strlen(config->bucket);
+    }
+    (void)len;                  /* avoid compiler warning when NDEBUG defined 
*/
     assert(len < bufsiz);
     return resource;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/http_io.h new/s3backer-1.3.5/http_io.h
--- old/s3backer-1.3.4/http_io.h        2011-02-01 18:31:15.000000000 +0100
+++ new/s3backer-1.3.5/http_io.h        2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: http_io.h 448 2011-02-01 17:31:15Z archie.cobbs $
+ * $Id: http_io.h 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 /* Upload/download indexes */
@@ -106,6 +106,5 @@
 /* http_io.c */
 extern struct s3backer_store *http_io_create(struct http_io_conf *config);
 extern void http_io_get_stats(struct s3backer_store *s3b, struct http_io_stats 
*stats);
-extern int http_io_detect_sizes(struct s3backer_store *s3b, off_t *file_sizep, 
u_int *block_sizep);
 extern int http_io_parse_block(struct http_io_conf *config, const char *name, 
s3b_block_t *block_num);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/main.c new/s3backer-1.3.5/main.c
--- old/s3backer-1.3.4/main.c   2013-03-04 19:31:21.000000000 +0100
+++ new/s3backer-1.3.5/main.c   2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: main.c 470 2013-03-04 18:31:13Z archie.cobbs $
+ * $Id: main.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -29,6 +29,7 @@
 #include "http_io.h"
 #include "s3b_config.h"
 #include "erase.h"
+#include "reset.h"
 
 int
 main(int argc, char **argv)
@@ -38,7 +39,7 @@
 
     /* Get configuration */
     if ((config = s3backer_get_config(argc, argv)) == NULL)
-        exit(1);
+        return 1;
 
     /* Handle `--erase' flag */
     if (config->erase) {
@@ -46,6 +47,13 @@
             return 1;
         return 0;
     }
+
+    /* Handle `--reset' flag */
+    if (config->reset) {
+        if (s3backer_reset(config) != 0)
+            return 1;
+        return 0;
+    }
 
     /* Get FUSE operation hooks */
     fuse_ops = fuse_ops_create(&config->fuse_ops);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/reset.c new/s3backer-1.3.5/reset.c
--- old/s3backer-1.3.4/reset.c  1970-01-01 01:00:00.000000000 +0100
+++ new/s3backer-1.3.5/reset.c  2013-05-11 19:07:54.000000000 +0200
@@ -0,0 +1,68 @@
+
+/*
+ * s3backer - FUSE-based single file backing store via Amazon S3
+ * 
+ * Copyright 2008-2011 Archie L. Cobbs <[email protected]>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * $Id: reset.c 482 2013-05-11 17:07:49Z archie.cobbs $
+ */
+
+#include "s3backer.h"
+#include "block_cache.h"
+#include "ec_protect.h"
+#include "fuse_ops.h"
+#include "http_io.h"
+#include "test_io.h"
+#include "s3b_config.h"
+#include "reset.h"
+
+int
+s3backer_reset(struct s3b_config *config)
+{
+    struct s3backer_store *s3b = NULL;
+    int ok = 0;
+    int r;
+
+    /* Logging */
+    if (!config->quiet)
+        warnx("resetting mounted flag for %s", config->description);
+
+    /* Create temporary lower layer */
+    if ((s3b = config->test ? test_io_create(&config->http_io) : 
http_io_create(&config->http_io)) == NULL) {
+        warnx(config->test ? "test_io_create" : "http_io_create");
+        goto fail;
+    }
+
+    /* Clear mounted flag */
+    if ((r = (*s3b->set_mounted)(s3b, NULL, 0)) != 0) {
+        warnx("error clearing mounted flag: %s", strerror(r));
+        goto fail;
+    }
+
+    /* Success */
+    if (!config->quiet)
+        warnx("done");
+    ok = 1;
+
+fail:
+    /* Clean up */
+    if (s3b != NULL)
+        (*s3b->destroy)(s3b);
+    return ok ? 0 : -1;
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/reset.h new/s3backer-1.3.5/reset.h
--- old/s3backer-1.3.4/reset.h  1970-01-01 01:00:00.000000000 +0100
+++ new/s3backer-1.3.5/reset.h  2013-05-11 19:07:54.000000000 +0200
@@ -0,0 +1,27 @@
+
+/*
+ * s3backer - FUSE-based single file backing store via Amazon S3
+ * 
+ * Copyright 2008-2011 Archie L. Cobbs <[email protected]>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * $Id: reset.h 482 2013-05-11 17:07:49Z archie.cobbs $
+ */
+
+/* reset.c */
+extern int s3backer_reset(struct s3b_config *config);
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/s3b_config.c 
new/s3backer-1.3.5/s3b_config.c
--- old/s3backer-1.3.4/s3b_config.c     2012-06-25 19:16:14.000000000 +0200
+++ new/s3backer-1.3.5/s3b_config.c     2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: s3b_config.c 468 2012-06-25 17:16:14Z archie.cobbs $
+ * $Id: s3b_config.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -170,6 +170,7 @@
     .quiet=                 0,
     .erase=                 0,
     .no_auto_detect=        0,
+    .reset=                 0,
     .log=                   syslog_logger
 };
 
@@ -288,6 +289,11 @@
         .value=     1
     },
     {
+        .templ=     "--reset-mounted-flag",
+        .offset=    offsetof(struct s3b_config, reset),
+        .value=     1
+    },
+    {
         .templ=     "--vhost",
         .offset=    offsetof(struct s3b_config, http_io.vhost),
         .value=     1
@@ -529,10 +535,15 @@
     return &config;
 }
 
+/*
+ * Create the s3backer_store used at runtime. This method is invoked by 
fuse_op_init().
+ */
 struct s3backer_store *
 s3backer_create_store(struct s3b_config *conf)
 {
     struct s3backer_store *store;
+    int mounted;
+    int r;
 
     /* Sanity check */
     if (http_io_store != NULL || test_io_store != NULL)
@@ -551,29 +562,43 @@
 
     /* Create eventual consistency protection layer (if desired) */
     if (conf->ec_protect.cache_size > 0) {
-        if ((ec_protect_store = ec_protect_create(&conf->ec_protect, store)) 
== NULL) {
-            (*store->destroy)(store);
-            http_io_store = NULL;
-            test_io_store = NULL;
-            return NULL;
-        }
+        if ((ec_protect_store = ec_protect_create(&conf->ec_protect, store)) 
== NULL) 
+            goto fail;
         store = ec_protect_store;
     }
 
     /* Create block cache layer (if desired) */
     if (conf->block_cache.cache_size > 0) {
-        if ((block_cache_store = block_cache_create(&conf->block_cache, 
store)) == NULL) {
-            (*store->destroy)(store);
-            ec_protect_store = NULL;
-            http_io_store = NULL;
-            test_io_store = NULL;
-            return NULL;
-        }
+        if ((block_cache_store = block_cache_create(&conf->block_cache, 
store)) == NULL)
+            goto fail;
         store = block_cache_store;
     }
 
+    /* Set mounted flag and check previous value one last time */
+    r = (*store->set_mounted)(store, &mounted, conf->fuse_ops.read_only ? -1 : 
1);
+    if (r != 0) {
+        (*conf->log)(LOG_ERR, "error reading mounted flag on %s: %s",
+          conf->description, strerror(r));
+        goto fail;
+    }
+    if (mounted) {
+        if (!conf->force) {
+            (*conf->log)(LOG_ERR, "%s appears to be mounted by another 
s3backer process", config.description);
+            goto fail;
+        }
+    }
+
     /* Done */
     return store;
+
+fail:
+    if (store != NULL)
+        (*store->destroy)(store);
+    block_cache_store = NULL;
+    ec_protect_store = NULL;
+    http_io_store = NULL;
+    test_io_store = NULL;
+    return NULL;
 }
 
 /****************************************************************************
@@ -1125,9 +1150,9 @@
     }
 
     /* Check mount point */
-    if (config.erase) {
+    if (config.erase || config.reset) {
         if (config.mount != NULL) {
-            warnx("no mount point required with `--erase'");
+            warnx("no mount point should be specified with `--erase' or 
`--reset-mounted-flag'");
             return -1;
         }
     } else {
@@ -1164,7 +1189,7 @@
             err(1, "http_io_create");
         if (!config.quiet)
             warnx("auto-detecting block size and total file size...");
-        r = http_io_detect_sizes(s3b, &auto_file_size, &auto_block_size);
+        r = (*s3b->meta_data)(s3b, &auto_file_size, &auto_block_size);
         (*s3b->destroy)(s3b);
     }
 
@@ -1207,7 +1232,6 @@
         }
         break;
     case ENOENT:
-    case ENXIO:
     {
         const char *why = config.no_auto_detect ? "disabled" : "failed";
         int config_block_size = config.block_size;
@@ -1226,10 +1250,35 @@
     }
     default:
         errno = r;
-        err(1, "can't read block zero meta-data");
+        err(1, "can't read data store meta-data");
         break;
     }
 
+    /* Check whether already mounted */
+    if (!config.test && !config.erase && !config.reset) {
+        int mounted;
+
+        config.http_io.debug = config.debug;
+        config.http_io.quiet = config.quiet;
+        config.http_io.log = config.log;
+        if ((s3b = http_io_create(&config.http_io)) == NULL)
+            err(1, "http_io_create");
+        r = (*s3b->set_mounted)(s3b, &mounted, -1);
+        (*s3b->destroy)(s3b);
+        if (r != 0) {
+            errno = r;
+            err(1, "error reading mounted flag");
+        }
+        if (mounted) {
+            if (!config.force)
+                errx(1, "error: %s appears to be already mounted", 
config.description);
+            if (!config.quiet) {
+                warnx("warning: filesystem appears already mounted but you 
said `--force'\n"
+                  " so I'll proceed anyway even though your data may get 
corrupted.\n");
+            }
+        }
+    }
+
     /* Check computed block and file sizes */
     if (config.block_size != (1 << (ffs(config.block_size) - 1))) {
         warnx("block size must be a power of 2");
@@ -1319,7 +1368,7 @@
     config.fuse_ops.log = config.log;
 
     /* If `--listBlocks' was given, build non-empty block bitmap */
-    if (config.erase)
+    if (config.erase || config.reset)
         config.list_blocks = 0;
     if (config.list_blocks) {
         struct s3backer_store *temp_store;
@@ -1505,6 +1554,7 @@
     fprintf(stderr, "\ts3backer [options] bucket /mount/point\n");
     fprintf(stderr, "\ts3backer --test [options] directory /mount/point\n");
     fprintf(stderr, "\ts3backer --erase [options] bucket\n");
+    fprintf(stderr, "\ts3backer --reset-mounted-flag [options] bucket\n");
     fprintf(stderr, "Options:\n");
     fprintf(stderr, "\t--%-27s %s\n", "accessFile=FILE", "File containing 
`accessID:accessKey' pairs");
     fprintf(stderr, "\t--%-27s %s\n", "accessId=ID", "S3 access key ID");
@@ -1529,7 +1579,7 @@
     fprintf(stderr, "\t--%-27s %s\n", "debug", "Enable logging of debug 
messages");
     fprintf(stderr, "\t--%-27s %s\n", "debug-http", "Print HTTP headers to 
standard output");
     fprintf(stderr, "\t--%-27s %s\n", "directIO", "Disable kernel caching of 
the backed file");
-    fprintf(stderr, "\t--%-27s %s\n", "encryption[=CIPHER]", "Enable 
encryption (implies `--compress')");
+    fprintf(stderr, "\t--%-27s %s\n", "encrypt[=CIPHER]", "Enable encryption 
(implies `--compress')");
     fprintf(stderr, "\t--%-27s %s\n", "erase", "Erase all blocks in the 
filesystem");
     fprintf(stderr, "\t--%-27s %s\n", "fileMode=MODE", "Permissions of backed 
file in filesystem");
     fprintf(stderr, "\t--%-27s %s\n", "filename=NAME", "Name of backed file in 
filesystem");
@@ -1551,6 +1601,7 @@
     fprintf(stderr, "\t--%-27s %s\n", "readAhead=NUM", "Number of blocks to 
read-ahead");
     fprintf(stderr, "\t--%-27s %s\n", "readAheadTrigger=NUM", "# of 
sequentially read blocks to trigger read-ahead");
     fprintf(stderr, "\t--%-27s %s\n", "readOnly", "Return `Read-only file 
system' error for write attempts");
+    fprintf(stderr, "\t--%-27s %s\n", "reset-mounted-flag", "Reset `already 
mounted' flag in the filesystem");
     fprintf(stderr, "\t--%-27s %s\n", "rrs", "Target written blocks for 
Reduced Redundancy Storage");
     fprintf(stderr, "\t--%-27s %s\n", "size=SIZE", "File size (with optional 
suffix 'K', 'M', 'G', etc.)");
     fprintf(stderr, "\t--%-27s %s\n", "ssl", "Same as --baseURL " 
S3_BASE_URL_HTTPS);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/s3b_config.h 
new/s3backer-1.3.5/s3b_config.h
--- old/s3backer-1.3.4/s3b_config.h     2011-02-01 18:31:15.000000000 +0100
+++ new/s3backer-1.3.5/s3b_config.h     2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: s3b_config.h 448 2011-02-01 17:31:15Z archie.cobbs $
+ * $Id: s3b_config.h 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 /* Overal application configuration info */
@@ -40,6 +40,7 @@
     off_t                       num_blocks;
     int                         debug;
     int                         erase;
+    int                         reset;
     int                         quiet;
     int                         force;
     int                         test;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/s3backer.1 
new/s3backer-1.3.5/s3backer.1
--- old/s3backer-1.3.4/s3backer.1       2011-08-04 22:35:12.000000000 +0200
+++ new/s3backer-1.3.5/s3backer.1       2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
 .\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 .\" 02110-1301, USA.
 .\"
-.\" $Id: s3backer.1 457 2011-08-04 20:35:12Z archie.cobbs $
+.\" $Id: s3backer.1 482 2013-05-11 17:07:49Z archie.cobbs $
 .\"
 .Dd September 7, 2009
 .Dt S3BACKER 1
@@ -49,6 +49,13 @@
 .Op options
 .Ar bucket
 .Ek
+.Pp
+.Nm s3backer
+.Bk -words
+.Fl \-reset-mounted-flag
+.Op options
+.Ar bucket
+.Ek
 .Sh DESCRIPTION
 .Nm
 is a filesystem that contains a single file backed by the Amazon Simple 
Storage Service (Amazon S3).
@@ -235,8 +242,17 @@
 .Nm
 filesystem is not a distributed filesystem and does not support simultaneous 
read/write mounts.
 (This is not something you would normally do with a hard-disk partition 
either.)
+As a safety measure,
+.Nm
+attempts to detect this situation using an 'already mounted' flag
+in the data store, and will fail to start if it does.
+.Pp
+This detection may produce a false positive if a former
 .Nm
-does not detect this situation; it is up to the user to ensure that it doesn't 
happen.
+process was not shutdown cleanly; if so, the
+.Fl \-reset-mounted-flag
+flag can be used to reset the 'already mounted' flag.
+But see also BUGS below.
 .Ss Statistics File
 .Nm
 populates the filesystem with a human-readable statistics file.
@@ -465,10 +481,11 @@
 This flag implies
 .Fl \-compress .
 .It Fl \-erase
-Completely erase the file system by deleting all non-zero blocks, and then 
exit.
+Completely erase the file system by deleting all non-zero blocks, clear the 
'already mounted' flag, and then exit.
 User confirmation is required unless the
 .Fl \-force
 flag is also given.
+Note, no simultaneous mount detection is performed in this case.
 .Pp
 This option implies
 .Fl \-listBlocks .
@@ -489,12 +506,33 @@
 .Fl \-blockSize
 or
 .Fl \-size
-disagrees with the auto-detected value.
-This is will certainly lead to garbled data and should be avoided for normal 
use.
+disagrees with the auto-detected value, or
+.Nm
+detects that another
+.Nm
+instance is still mounted on top of the same S3 bucket (and prefix).
+In any of these cases, proceeding will lead to corrupted data, so the
+.Fl \-force
+flag should be avoided for normal use.
+.Pp
+The simultaneous mount detection can produce a false positive when a previous
+.Nm
+instance was not shut down cleanly.
+In this case, don't use
+.Fl \-force
+but rather run
+.Nm
+once with the
+.Fl \-reset-mounted-flag
+flag.
 .Pp
 If
 .Fl \-erase
-is given, proceed without user confirmation.
+is given,
+.Fl \-force
+causes
+.Nm
+to proceed without user confirmation.
 .It Fl h Fl \-help
 Print a help message and exit.
 .It Fl \-initialRetryPause=MILLIS
@@ -620,6 +658,20 @@
 in response to any attempt to write.
 This flag also changes the default mode of the backed file from 0600 to 0400
 and disables the MD5 checksum cache.
+.It Fl \-reset-mounted-flag
+Reset the 'already mounted' flag on the underlying S3 data store.
+.Pp
+.Nm
+detects simultaneous mounts by checking a special flag.
+If a previous invocation of
+.Nm
+was not shut down cleanly, the flag may not have been cleared.
+Running
+.Nm
+.Fl \-erase
+will clear it manually.
+But see also BUGS below.
+.Pp
 .It Fl \-rrs
 When writing blocks, specify Reduced Redundancy Storage.
 .It Fl \-size=SIZE
@@ -755,6 +807,22 @@
 .%O http://www.google.com/search?q=linux+page+cache
 .Re
 .Sh BUGS
+Due to a design flaw in FUSE, an unmount of the
+.Nm
+filesystem will complete successfully before
+.Nm
+has finished writing back all dirty blocks.
+Therefore, when using the block cache, attempts to remount the same bucket and 
prefix
+may fail with an 'already mounted' error while the former
+.Nm
+process finishes flusing its cache.
+Before assuming a false positive and using
+.Fl \-reset-mounted-flag,
+ensure that any previous
+.Nm
+process attached to the same bucket and prefix has exited.
+See issue #40 for details.
+.Pp
 For cache space efficiency,
 .Nm
 uses 32 bit values to index individual blocks.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/s3backer.h 
new/s3backer-1.3.5/s3backer.h
--- old/s3backer-1.3.4/s3backer.h       2013-03-04 19:31:21.000000000 +0100
+++ new/s3backer-1.3.5/s3backer.h       2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: s3backer.h 470 2013-03-04 18:31:13Z archie.cobbs $
+ * $Id: s3backer.h 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "config.h"
@@ -107,6 +107,35 @@
 struct s3backer_store {
 
     /*
+     * Get meta-data associated with the underlying store.
+     *
+     * The information we acquire is:
+     *  o Block size
+     *  o Total size
+     *
+     * Returns:
+     *
+     *  0       Success
+     *  ENOENT  Information not found
+     *  Other   Other error
+     */
+    int         (*meta_data)(struct s3backer_store *s3b, off_t *file_sizep, 
u_int *block_sizep);
+
+    /*
+     * Read and (optionally) set the mounted flag.
+     *
+     * Previous value is returned in *old_valuep (if not NULL).
+     *
+     * new_value can be:
+     *  -1      Don't change it
+     *   0      Clear it
+     *   1      Set it
+     *
+     * Returns zero on success or a (positive) errno value on error.
+     */
+    int         (*set_mounted)(struct s3backer_store *s3b, int *old_valuep, 
int new_value);
+
+    /*
      * Read one block. Never-written-to blocks will return all zeroes.
      *
      * If not NULL, 'actual_md5' should be filled in with a value suitable for 
the 'expect_md5' parameter,
@@ -165,6 +194,11 @@
     int         (*list_blocks)(struct s3backer_store *s3b, block_list_func_t 
*callback, void *arg);
 
     /*
+     * Sync any dirty data to the underlying data store.
+     */
+    int         (*flush)(struct s3backer_store *s3b);
+
+    /*
      * Destroy this instance.
      */
     void        (*destroy)(struct s3backer_store *s3b);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/s3backer.spec 
new/s3backer-1.3.5/s3backer.spec
--- old/s3backer-1.3.4/s3backer.spec    2013-04-03 03:45:29.000000000 +0200
+++ new/s3backer-1.3.5/s3backer.spec    2013-05-29 19:43:31.000000000 +0200
@@ -17,7 +17,7 @@
 # 
 
 Name:           s3backer
-Version:        1.3.4
+Version:        1.3.5
 Release:        1
 License:        GNU General Public License, Version 2
 Summary:        FUSE-based single file backing store via Amazon S3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/svnrev.c new/s3backer-1.3.5/svnrev.c
--- old/s3backer-1.3.4/svnrev.c 2013-04-03 03:45:30.000000000 +0200
+++ new/s3backer-1.3.5/svnrev.c 2013-05-29 19:43:32.000000000 +0200
@@ -1 +1 @@
-const int s3backer_svnrev = 476;
+const int s3backer_svnrev = 485;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3backer-1.3.4/test_io.c new/s3backer-1.3.5/test_io.c
--- old/s3backer-1.3.4/test_io.c        2011-02-01 18:31:15.000000000 +0100
+++ new/s3backer-1.3.5/test_io.c        2013-05-11 19:07:54.000000000 +0200
@@ -19,7 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  *
- * $Id: test_io.c 448 2011-02-01 17:31:15Z archie.cobbs $
+ * $Id: test_io.c 482 2013-05-11 17:07:49Z archie.cobbs $
  */
 
 #include "s3backer.h"
@@ -37,6 +37,8 @@
 };
 
 /* s3backer_store functions */
+static int test_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, 
u_int *block_sizep);
+static int test_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, 
int new_value);
 static int test_io_read_block(struct s3backer_store *s3b, s3b_block_t 
block_num, void *dest,
   u_char *actual_md5, const u_char *expect_md5, int strict);
 static int test_io_write_block(struct s3backer_store *s3b, s3b_block_t 
block_num, const void *src, u_char *md5,
@@ -44,6 +46,7 @@
 static int test_io_read_block_part(struct s3backer_store *s3b, s3b_block_t 
block_num, u_int off, u_int len, void *dest);
 static int test_io_write_block_part(struct s3backer_store *s3b, s3b_block_t 
block_num, u_int off, u_int len, const void *src);
 static int test_io_list_blocks(struct s3backer_store *s3b, block_list_func_t 
*callback, void *arg);
+static int test_io_flush(struct s3backer_store *s3b);
 static void test_io_destroy(struct s3backer_store *s3b);
 
 /*
@@ -60,11 +63,14 @@
     /* Initialize structures */
     if ((s3b = calloc(1, sizeof(*s3b))) == NULL)
         return NULL;
+    s3b->meta_data = test_io_meta_data;
+    s3b->set_mounted = test_io_set_mounted;
     s3b->read_block = test_io_read_block;
     s3b->write_block = test_io_write_block;
     s3b->read_block_part = test_io_read_block_part;
     s3b->write_block_part = test_io_write_block_part;
     s3b->list_blocks = test_io_list_blocks;
+    s3b->flush = test_io_flush;
     s3b->destroy = test_io_destroy;
     if ((priv = calloc(1, sizeof(*priv) + config->block_size)) == NULL) {
         free(s3b);
@@ -81,9 +87,26 @@
     return s3b;
 }
 
-/*
- * Destructor
- */
+static int
+test_io_meta_data(struct s3backer_store *s3b, off_t *file_sizep, u_int 
*block_sizep)
+{
+    return 0;
+}
+
+static int
+test_io_set_mounted(struct s3backer_store *s3b, int *old_valuep, int new_value)
+{
+    if (old_valuep != NULL)
+        *old_valuep = 0;
+    return 0;
+}
+
+static int
+test_io_flush(struct s3backer_store *const s3b)
+{
+    return 0;
+}
+
 static void
 test_io_destroy(struct s3backer_store *const s3b)
 {

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

Reply via email to