summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kettlewell <rjk@terraraq.org.uk>2018-02-15 20:27:38 +0000
committerRichard Kettlewell <rjk@terraraq.org.uk>2018-07-27 18:26:58 +0100
commit40456b4f710fe5b8cf5a25b8ac412dc5c7094957 (patch)
tree5e9113e3317b1f942402c71347d1ba52cba8fbd9
parent39c681b56df58660f23d10258a410a648266b0b7 (diff)
Store directories (normally) have to be mount points
This can be disabled with new options to store and store-pattern. fixes #42
-rw-r--r--doc/CHANGES.html14
-rw-r--r--doc/rsbackup.510
-rw-r--r--src/ConfDirective.cc31
-rw-r--r--src/Store.cc10
-rw-r--r--src/Store.h10
-rw-r--r--src/rsbackup.cc2
-rwxr-xr-xtests/glob-store4
-rwxr-xr-xtests/setup.sh6
8 files changed, 70 insertions, 17 deletions
diff --git a/doc/CHANGES.html b/doc/CHANGES.html
index 9ccd666..ad2564e 100644
--- a/doc/CHANGES.html
+++ b/doc/CHANGES.html
@@ -15,6 +15,20 @@
href="https://github.com/ewxrjk/rsbackup">rsbackup
in git</a> for detailed change history.</p>
+ <h2>Changes In rsbackup 5.1</h2>
+
+ <ul>
+
+ <li>Store directories are now normally required to be mount
+ points. See the description of <code>store</code>
+ and <code>store-pattern</code>
+ in <a href="rsbackup.5.html">rsbackup(5)</a> for options to
+ restore the previous behavior.
+ Fixes <a href="https://github.com/ewxrjk/rsbackup/issues/42">issue
+ #42</a>.</li>
+
+ </ul>
+
<h2>Changes In rsbackup 5.0</h2>
<ul>
diff --git a/doc/rsbackup.5 b/doc/rsbackup.5
index c6609d6..c5b0de5 100644
--- a/doc/rsbackup.5
+++ b/doc/rsbackup.5
@@ -101,14 +101,20 @@ If true, backups are public.
Normally backups must only be accessible by the calling user.
This option suppresses the check.
.TP
-.B store \fIPATH\fR
+.B store \fR[\fB--mounted|--no-mounted\fR] \fIPATH\fR
A path at which a backup device may be mounted.
This can be used multiple times.
+.IP
+With the \fB--mounted\fR option (which is the default),
+\fIPATH\fR must be a mount point.
+With \fB--no-mounted\fR it need not be a mount point.
.TP
-.B store\-pattern \fIPATTERN\fR
+.B store\-pattern \fR[\fB-mounted|-nomounted\fR] \fIPATTERN\fR
A \fBglob\fR(7) pattern matching paths at which a backup device may be
mounted.
This can be used multiple times.
+.IP
+See the description of \fBstore\fR above for the meanings of the options.
.SS "Report Directives"
These are global directives that affect only the HTML report.
.TP
diff --git a/src/ConfDirective.cc b/src/ConfDirective.cc
index c10f762..7cef053 100644
--- a/src/ConfDirective.cc
+++ b/src/ConfDirective.cc
@@ -139,22 +139,43 @@ void ColorDirective::set_packed(ConfContext &cc, size_t n, int radix) const {
// Global directives ----------------------------------------------------------
+size_t parseStoreArguments(const ConfContext &cc, bool &mounted) {
+ mounted = true;
+ size_t i = 1;
+ while(i < cc.bits.size() && cc.bits[i][0] == '-') {
+ if(cc.bits[i] == "--mounted")
+ mounted = true;
+ else if(cc.bits[i] == "--no-mounted")
+ mounted = false;
+ else
+ throw SyntaxError("unrecognized store option");
+ ++i;
+ }
+ if(i >= cc.bits.size())
+ throw SyntaxError("missing store path");
+ return i;
+}
+
/** @brief The @c store directive */
static const struct StoreDirective: public ConfDirective {
- StoreDirective(): ConfDirective("store", 1, 1) {}
+ StoreDirective(): ConfDirective("store", 1, INT_MAX) {}
void set(ConfContext &cc) const override {
- cc.conf->stores[cc.bits[1]] = new Store(cc.bits[1]);
+ bool mounted;
+ size_t i = parseStoreArguments(cc, mounted);
+ cc.conf->stores[cc.bits[i]] = new Store(cc.bits[i], mounted);
}
} store_directive;
/** @brief The @c store-pattern directive */
static const struct StorePatternDirective: public ConfDirective {
- StorePatternDirective(): ConfDirective("store-pattern", 1, 1) {}
+ StorePatternDirective(): ConfDirective("store-pattern", 1, INT_MAX) {}
void set(ConfContext &cc) const override {
std::vector<std::string> files;
- globFiles(files, cc.bits[1], GLOB_NOCHECK);
+ bool mounted;
+ size_t i = parseStoreArguments(cc, mounted);
+ globFiles(files, cc.bits[i], GLOB_NOCHECK);
for(auto &file: files)
- cc.conf->stores[file] = new Store(file);
+ cc.conf->stores[file] = new Store(file, mounted);
}
} store_pattern_directive;
diff --git a/src/Store.cc b/src/Store.cc
index 5add94f..543c7cd 100644
--- a/src/Store.cc
+++ b/src/Store.cc
@@ -1,4 +1,4 @@
-// Copyright © 2011, 2012 Richard Kettlewell.
+// Copyright © 2011-13, 2015-18 Richard Kettlewell.
//
// 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
@@ -34,6 +34,14 @@ void Store::identify() {
return; // already identified
if(stat(path.c_str(), &sb) < 0)
throw BadStore("store '" + path + "' does not exist");
+ if(mounted) {
+ const std::string parent_path = path + "/..";
+ struct stat parent_sb;
+ if(stat(parent_path.c_str(), &parent_sb) < 0)
+ throw FatalStoreError("cannot stat '" + parent_path);
+ if(sb.st_dev == parent_sb.st_dev)
+ throw UnavailableStore("store '" + path + "' is not mounted");
+ }
// Make sure backup devices are mounted
preDeviceAccess();
// Read the device name
diff --git a/src/Store.h b/src/Store.h
index 82a4058..d812719 100644
--- a/src/Store.h
+++ b/src/Store.h
@@ -1,5 +1,5 @@
// -*-C++-*-
-// Copyright © 2011, 2012, 2014, 2015 Richard Kettlewell.
+// Copyright © 2011, 2012, 2014, 2015, 2018 Richard Kettlewell.
//
// 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
@@ -32,7 +32,8 @@ public:
/** @brief Constructor
* @param path_ Location of store
*/
- Store(const std::string &path_): path(path_) {}
+ Store(const std::string &path_, bool mounted_):
+ path(path_), mounted(mounted_) {}
/** @brief Possible states */
enum State {
@@ -43,9 +44,12 @@ public:
Enabled = 2,
};
- /** @param Location of store */
+ /** @brief Location of store */
std::string path;
+ /** @brief True if path must be a mount point */
+ bool mounted;
+
/** @param Device mounted at this store
*
* Set to null pointer before checking, or if no device is mounted here
diff --git a/src/rsbackup.cc b/src/rsbackup.cc
index 8c6c0e1..e1896d2 100644
--- a/src/rsbackup.cc
+++ b/src/rsbackup.cc
@@ -58,7 +58,7 @@ int main(int argc, char **argv) {
for(auto &s: command.stores) {
auto it = config.stores.find(s);
if(it == config.stores.end())
- config.stores[s] = new Store(s);
+ config.stores[s] = new Store(s, false/*TODO*/);
else
it->second->state = Store::Enabled;
}
diff --git a/tests/glob-store b/tests/glob-store
index 5d24749..20c7c12 100755
--- a/tests/glob-store
+++ b/tests/glob-store
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright © 2011, 2012, 2014, 2015 Richard Kettlewell.
+# Copyright © 2011, 2012, 2014, 2015, 2018 Richard Kettlewell.
#
# 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
@@ -22,7 +22,7 @@ export EXPECT_STATUS=ok
sed < ${WORKSPACE}/config > ${WORKSPACE}/config.new \
'/^store /d';
-echo "store-pattern ${WORKSPACE}/store*" >>${WORKSPACE}/config.new
+echo "store-pattern --no-mounted ${WORKSPACE}/store*" >>${WORKSPACE}/config.new
mv -f ${WORKSPACE}/config.new ${WORKSPACE}/config
echo "| Create backup for everything using glob-pattern directive"
diff --git a/tests/setup.sh b/tests/setup.sh
index b521208..c82d4cc 100755
--- a/tests/setup.sh
+++ b/tests/setup.sh
@@ -1,4 +1,4 @@
-# Copyright © 2011, 2012, 2014-17 Richard Kettlewell.
+# Copyright © 2011, 2012, 2014-18 Richard Kettlewell.
#
# 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
@@ -41,12 +41,12 @@ setup() {
mkdir ${WORKSPACE}/store1
echo device1 > ${WORKSPACE}/store1/device-id
- echo "store ${WORKSPACE}/store1" >> ${WORKSPACE}/config
+ echo "store --no-mounted ${WORKSPACE}/store1" >> ${WORKSPACE}/config
echo "device \"device1\"" >> ${WORKSPACE}/config
mkdir ${WORKSPACE}/store2
echo device2 > ${WORKSPACE}/store2/device-id
- echo "store ${WORKSPACE}/store2" >>${WORKSPACE}/config
+ echo "store --no-mounted ${WORKSPACE}/store2" >>${WORKSPACE}/config
echo "device device2" >> ${WORKSPACE}/config
echo "public true" >> ${WORKSPACE}/config