Bladeren bron

Merge branch 'master' of github.com:OWeh55/kind

Wolfgang Ortmann 7 jaren geleden
bovenliggende
commit
facc577c1f
17 gewijzigde bestanden met toevoegingen van 174 en 120 verwijderingen
  1. 8 0
      .gitignore
  2. BIN
      bin/kind
  3. 1 16
      src/DateTime.cpp
  4. 10 10
      src/DateTime.h
  5. 3 4
      src/FileName.cpp
  6. 2 3
      src/Image.cpp
  7. 1 0
      src/Image.h
  8. 19 5
      src/KindConfig.cpp
  9. 3 3
      src/KindConfig.h
  10. 3 5
      src/Lexer.cpp
  11. 1 1
      src/Makefile
  12. 0 2
      src/Strings.h
  13. 14 9
      src/excludetools.cpp
  14. 11 4
      src/expiretools.cpp
  15. 9 2
      src/filetools.cpp
  16. 88 55
      src/kind.ag
  17. 1 1
      src/stringtools.cpp

+ 8 - 0
.gitignore

@@ -0,0 +1,8 @@
+*.o
+*.orig
+src/stot
+src/stot.cpp
+src/depend
+src/kind
+src/kind.cpp
+*~

BIN
bin/kind


+ 1 - 16
src/DateTime.cpp

@@ -21,7 +21,7 @@ void DateTime::get(int& year, int& month, int& mday,
 
 DateTime::DateTime(int Y, int M, int D, int h, int m, int s)
 {
-  struct tm ltm;
+  tm ltm;
   ltm.tm_year = Y - 1900;
   ltm.tm_mon = M - 1;
   ltm.tm_mday = D;
@@ -32,21 +32,6 @@ DateTime::DateTime(int Y, int M, int D, int h, int m, int s)
   theTime = mktime(&ltm);
 }
 
-#if 0
-struct tm
-{
-  int tm_sec;    /* Seconds (0-60) */
-  int tm_min;    /* Minutes (0-59) */
-  int tm_hour;   /* Hours (0-23) */
-  int tm_mday;   /* Day of the month (1-31) */
-  int tm_mon;    /* Month (0-11) */
-  int tm_year;   /* Year - 1900 */
-  int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
-  int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
-  int tm_isdst;  /* Daylight saving time */
-};
-#endif
-
 bool DateTime::match(const set<int>& Y, const set<int>& M, const set<int>& D,
                      const set<int>& W,
                      const set<int>& h, const set<int>& m, const set<int>& s) const

+ 10 - 10
src/DateTime.h

@@ -11,7 +11,7 @@ class DateTime
 public:
   static DateTime now()
   {
-    return DateTime(time(NULL));
+    return DateTime(time(nullptr));
   }
 
   DateTime(): theTime(0) {}
@@ -20,6 +20,11 @@ public:
 
   DateTime(int Y, int M, int D, int h, int m, int s);
 
+  void get(int& year, int& month, int& mday,
+           int& hour, int& min, int& sec) const;
+
+  std::string getString(char typ = 'h') const;
+
   friend DateTime operator+(const DateTime& t1, time_t t2)
   {
     return DateTime(t1.theTime + t2);
@@ -31,10 +36,10 @@ public:
     return *this;
   }
 
-  void get(int& year, int& month, int& mday,
-           int& hour, int& min, int& sec) const;
-
-  std::string getString(char typ = 'h') const;
+  friend DateTime operator-(const DateTime& t1, time_t t2)
+  {
+    return DateTime(t1.theTime - t2);
+  }
 
   const DateTime& operator-=(time_t t2)
   {
@@ -42,11 +47,6 @@ public:
     return *this;
   }
 
-  friend DateTime operator-(const DateTime& t1, time_t t2)
-  {
-    return DateTime(t1.theTime - t2);
-  }
-
   friend time_t operator-(const DateTime& t1, const DateTime& t2)
   {
     return t1.theTime - t2.theTime;

+ 3 - 4
src/FileName.cpp

@@ -64,7 +64,7 @@ void FileName::setName(const string& n)
 {
   for (unsigned int i = 0; i < n.size(); ++i)
     if (n[i] == pathdel)
-      throw Exception("Filename", "path delimiter in name");
+      throw Exception("Filename::setName", "path delimiter in name");
   name = n;
 }
 
@@ -73,9 +73,9 @@ void FileName::setExtension(const string& n)
   for (unsigned int i = 0; i < n.size(); ++i)
     {
       if (n[i] == extdel)
-        throw Exception("Filename", "extension delimiter in extension");
+        throw Exception("Filename::setExtension", "extension delimiter in extension");
       if (n[i] == pathdel)
-        throw Exception("Filename", "path delimiter in extension");
+        throw Exception("Filename::setExtension", "path delimiter in extension");
     }
   extension = n;
 }
@@ -144,4 +144,3 @@ int main(int argc, char** argv)
     }
 }
 #endif
-

+ 2 - 3
src/Image.cpp

@@ -11,7 +11,7 @@ using namespace std;
 Image::Image(const string& dir): name(dir)
 {
   FileName fn(name);
-  string dummy;// image "name"
+  string dummy; // image "name"
   stringToDate(fn.getName(), time, dummy);
   string expireFileName = name + "/expires";
 
@@ -26,7 +26,7 @@ Image::Image(const string& dir): name(dir)
       Strings expireText;
       file2Strings(expireFileName, expireText);
       if (expireText.empty())
-        throw Exception("expireDate", "expire empty");
+        throw Exception("expireDate", "expire file empty");
       stringToDate(expireText[0], expire, series);
       expireRule = expireText[1];
     }
@@ -42,7 +42,6 @@ void Image::printInfo() const
       cout << "created: " << time.getString('h') << endl;
       cout << "expires: " << expire.getString('h') << " -  " << timeString(expire - DateTime::now()) << endl;
     }
-
   else
     cout << "invalid" << endl;
 }

+ 1 - 0
src/Image.h

@@ -7,6 +7,7 @@
 #include "DateTime.h"
 #include "expiretools.h"
 
+// class decribing one image
 class Image
 {
 public:

+ 19 - 5
src/KindConfig.cpp

@@ -51,13 +51,27 @@ void KindConfig::addFile(const std::string& fn)
     }
 }
 
+int KindConfig::addOneFile(const std::vector<std::string>& fns)
+{
+  if (fns.empty())
+    throw Exception("Read config file", "file list empty");
+  unsigned int i = 0;
+  while (!fileExists(fns[i]) && i < fns.size())
+    i++;
+
+  if (i >= fns.size())
+    throw Exception("Read config file", "no file found");
+  addFile(fns[i]);
+  return i;
+}
+
 bool KindConfig::hasKey(std::string key) const
 {
   key = trim(key);
   auto it = settings.find(key);
   bool found = it != settings.end();
   if (found)
-    used[key]=true;
+    used[key] = true;
   return found;
 }
 
@@ -67,7 +81,7 @@ std::string KindConfig::getString(std::string key) const
   auto it = settings.find(key);
   if (it == settings.end())
     throw Exception("get config key", std::string("No key \"") + key + "\"");
-  used[key]=true;
+  used[key] = true;
   if (it->second.size() != 1)
     throw Exception("get config key", std::string("Key \"") + key + "\" is no single value");
   return it->second[0];
@@ -79,7 +93,7 @@ Strings KindConfig::getStrings(std::string key) const
   auto it = settings.find(key);
   if (it == settings.end())
     throw Exception("get config key", std::string("No key \"") + key + "\"");
-  used[key]=true;
+  used[key] = true;
   return it->second;
 }
 
@@ -89,7 +103,7 @@ bool KindConfig::getBool(std::string key) const
   auto it = settings.find(key);
   if (it == settings.end())
     return false;
-  used[key]=true;
+  used[key] = true;
   if (it->second.size() != 1)
     throw Exception("get config key", std::string("Key \"") + key + "\" is no single value");
   std::string val = it->second[0];
@@ -119,7 +133,7 @@ void KindConfig::warnUnused(const string& prefix) const
   for (auto it = settings.begin(); it != settings.end(); ++it)
     {
       if (used.count(it->first) == 0 || ! used[it->first])
-	cout << "Warning: setting " << it->first << " unused" << endl;
+        cout << "Warning: setting " << it->first << " unused" << endl;
     }
 }
 

+ 3 - 3
src/KindConfig.h

@@ -1,21 +1,21 @@
 #ifndef Kind_CONFIG_H
 #define Kind_CONFIG_H
 
-//#include <fstream>
 #include <map>
 #include <string>
 #include "Strings.h"
 #include "stringtools.h"
+#include "filetools.h"
 
 class KindConfig
 {
 public:
   KindConfig() {}
   KindConfig(const std::string& fn);
-  //  KindConfig(std::istream& is);
 
   void addFile(const std::string& fn);
-  //  void addFile(std::istream& is);
+  int addOneFile(const std::vector<std::string>& fns);
+
   void addString(const std::string& key, const std::string& value)
   {
     settings[key].push_back(value);

+ 3 - 5
src/Lexer.cpp

@@ -22,7 +22,8 @@ char Lexer::getChar()
 
 void Lexer::skipChar()
 {
-  pos++;
+  if (pos < str.size())
+    pos++;
 }
 
 void Lexer::skipWhiteSpace()
@@ -43,7 +44,7 @@ void Lexer::nextToken()
       if (isdigit(f))
         {
           // token is number
-          type = integer; // assume "integer"
+          type = integer; // assume "integer", changed later if necessarry
           // number
           f = nextChar();
           while (isdigit(f) || f == '.')
@@ -78,11 +79,9 @@ void Lexer::nextToken()
         }
       else if (isalpha(f))
         {
-          //    cout << "id"<<endl;
           // identifier
           type = identifier;
           f = nextChar();
-          //    cout << (int)f << " " << f << endl;
           while (isalnum(f))
             {
               token += f;
@@ -101,7 +100,6 @@ void Lexer::nextToken()
 
 long int Lexer::getInt()
 {
-  // cout << "type: " << type << " token:" << token << endl;
   if (type != integer)
     throw Exception("getInt", "integer value expected");
   int res = stol(token);

+ 1 - 1
src/Makefile

@@ -40,7 +40,7 @@ stot:	stot.o stringtools.o Lexer.o
 sshtest: sshtest.o filetools.o
 	$(CXX) $(LOPT) $(LIBRARY) -o sshtest sshtest.o filetools.o $(LIBS)	
 
-static: kind
+kind_static: kind
 	$(CXX) $(LOPT) $(LIBRARY) -static -o kind_static $(OBJECTS) $(LIBS)
 	strip kind_static
 	cp kind_static ../bin/kind

+ 0 - 2
src/Strings.h

@@ -19,6 +19,4 @@ public:
     return *this;
   }
 };
-
-
 #endif

+ 14 - 9
src/excludetools.cpp

@@ -34,11 +34,11 @@ Strings getExclusions(const KindConfig& conf)
           int rc;
           Strings excludedFiles = remoteExec(rshCommand, cmd, rc, debug);
           /*
-	    if (rc > 0)
-	    {
-	    // return Strings should contain error messages
-	    throw Exception("Find excludes", "Search for excludes failed");
-	    }
+          if (rc > 0)
+          {
+          // return Strings should contain error messages
+          throw Exception("Find excludes", "Search for excludes failed");
+          }
           */
           for (unsigned int i = 0; i < excludedFiles.size(); ++i)
             {
@@ -47,7 +47,7 @@ Strings getExclusions(const KindConfig& conf)
               debugPrint("Excluding: " + exclusions.back());
             }
         }
-      
+
       string userExcludeFile = conf.getString("userExcludeFile");
       if (!userExcludeFile.empty())
         {
@@ -58,10 +58,15 @@ Strings getExclusions(const KindConfig& conf)
           int rc;
           Strings excludes2 = remoteExec(rshCommand, getExcludeFileCommand, rc, debug);
           if (rc == 0)
-            exclusions += excludes2;
+            {
+              for (string s : excludes2)
+                {
+                  if (s[0] != '#')
+                    exclusions += s;
+                }
+            }
         } // if (shellMode)
-      
+
     }
   return exclusions;
 }
-

+ 11 - 4
src/expiretools.cpp

@@ -62,10 +62,17 @@ void stringToDate(const string& dateString, DateTime& t, string& label)
   int D = stoi(ss[3]);
   int h = stoi(ss[4]);
   int m = 0, s = 0;
-  if (ss.size() > 5) // longImageName
-    m = stoi(ss[5]);
-  if (ss.size() > 6)
-    s = stoi(ss[6]);
+  try    // longImageName
+    {
+      if (ss.size() > 5)
+        m = stoi(ss[5]);
+      if (ss.size() > 6)
+        s = stoi(ss[6]);
+    }
+  catch (const std::invalid_argument& ex)
+    {
+      // ignore this. image name may contain backup set name
+    }
   t = DateTime(Y, M, D, h, m, s);
 }
 

+ 9 - 2
src/filetools.cpp

@@ -1,3 +1,4 @@
+#define _FILE_OFFSET_BITS 64
 #include <stdio.h>
 #include <sys/file.h>
 #include <sys/stat.h>
@@ -241,7 +242,13 @@ Strings localExec(const std::string& cmd,
           if (debug)
             std::cout << ">>" << input << "<<" << std::endl;
         }
-      rc = pclose(fd);
+
+      int st = pclose(fd);
+      if (WIFEXITED(st))
+        rc = WEXITSTATUS(st);
+      else
+        rc = 0;
+
       if (debug)
         std::cout << "    result code: " << rc << std::endl;
     }
@@ -256,7 +263,7 @@ Strings localExec(const std::string& cmd,
   if (log.is_open())
     {
       log << "--------------------------------------------------------" << std::endl;
-      log << "result code: " << rc << std::endl;
+      log << "rsync exit value: " << rc << std::endl;
     }
   return res;
 }

+ 88 - 55
src/kind.ag

@@ -35,20 +35,20 @@
   prog: archiving backup
   %% Beschreibung Parameter
   % symbolischerName, Art, Typ,   Variablenname, Erklärung, Default-Wert
-  para: vault_or_group, required, string, vault, Vault to backup
+  para: vault_or_group, required, string, vault_or_group, Vault to backup
   %% Beschreibung der Optionen
   % kurz-Option, lang-Option, Typ, Variablenname, Erklärung, Default-Wert
   opt: c, masterconfig, string, masterConfig, Master config file, ""
   opt2: if not given or empty kind looks for
+  opt2:   /etc/kind.master
   opt2:   /etc/kind/master.conf
-  opt2:   /ffp/etc/kind/master.conf
   opt: f, full, void, fullImage, Force full image == initial backup, false
   opt: B, backup, void, doBackup, Backup, false
   opt: E, expire, void, doExpire, Expire, false
   opt: C, listconfig, void, listConfig, Show configuration, false
   opt: I, listimages, void, listImages, List data of images, false
-  opt2:   if none of backup, expire, listconfig and listimages is specified,
-  opt2:   backup and expire is assumed.
+  opt: V, vaultlist, void, listVault, List vault director[y|ies], false
+  opt2:   if no action is given, backup and expire is assumed.
   opt2:   listconfig and listimages cannot be combined with other actions
   opt: D, dryrun, Void, dryRun, Dry run (no real backup), false
   opt: F, forcebackup, string, forcedBackupSet, Create image for specified backup set, ""
@@ -122,22 +122,21 @@ void debugPrint(const string& text)
     cout << "    " << text << endl;
 }
 
-void readMasterConfig1(const string& fn, KindConfig& conf)
-{
-  verbosePrint("reading master config " + fn);
-  conf.addFile(fn);
-}
-
-void readMasterConfig(const string& fn, KindConfig& conf)
+void readMasterConfig(string fn, KindConfig& conf)
 {
   if (!fn.empty())  // master config given by user on commandline
-    readMasterConfig1(fn, conf);
-  else if (fileExists("/etc/kind/master.conf"))
-    readMasterConfig1("/etc/kind/master.conf", conf);
-  else if (fileExists("/ffp/etc/kind/master.conf"))
-    readMasterConfig1("/ffp/etc/kind/master.conf", conf);
+    conf.addFile(fn);
   else
-    throw Exception("MasterConfig", "no file");
+    {
+      vector<string> fns
+      {
+        "/etc/kind/master.conf",
+        "/etc/kind.master"
+      };
+      int i = conf.addOneFile(fns);
+      fn = fns[i];
+    }
+  verbosePrint("Read master config " + fn);
 }
 
 string findVault(const string& v)
@@ -160,10 +159,15 @@ string findVault(const string& v)
 void readVaultConfig(const string& vault, KindConfig& conf)
 {
   string vaultPath = findVault(vault);
-  const string& vaultConfigName = vaultPath + '/' + conf.getString("vaultConfigName");
-  verbosePrint("reading vault config:");
-  verbosePrint("  " + vaultConfigName);
-  conf.addFile(vaultConfigName);
+
+  Strings configNames = conf.getStrings("vaultConfigName");
+
+  vector<string> vaultConfigNames;
+  for (auto name : configNames)
+    vaultConfigNames.push_back(vaultPath + '/' + name);
+
+  int i = conf.addOneFile(vaultConfigNames);
+  verbosePrint("Read vault config " + vaultConfigNames[i]);
 
   // postprocessing
 
@@ -193,28 +197,21 @@ void readVaultConfig(const string& vault, KindConfig& conf)
     conf.setBool("useBackupSet", true);
   else
     conf.setBool("useBackupSet", false);
-  /*
-  if (conf.hasKey("userExcludeFile"))
-    {
-      string userExcludeCommand = "cat %path/" + conf.getString("userExcludeFile");
-      conf.addString("userExcludeCommand", userExcludeCommand);
-    }
-  */
 }
 
 string getImageName(const KindConfig& conf,
                     const DateTime& imageTime)
 {
-  bool nonPortable = false;
+  char invalidCharacter = 0;
   string imageName = conf.getString("imageName");
-  for (unsigned int i = 0; !nonPortable && i < imageName.size(); ++i)
+  for (unsigned int i = 0; invalidCharacter == 0 && i < imageName.size(); ++i)
     {
       char c = imageName[i];
       if (!isalnum(c) && c != '.' && c != '_')
-        nonPortable = true;
+        invalidCharacter = c;
     }
-  if (nonPortable)
-    throw Exception("getImageName", "Invalid character in image name " + imageName);
+  if (invalidCharacter != 0)
+    throw Exception("getImageName", string("Invalid character \'") + invalidCharacter + "\' in image name \"" + imageName + "\"");
 
   if (!imageName.empty())
     imageName += '-';
@@ -229,33 +226,35 @@ string getImageName(const KindConfig& conf,
   return imageFullName;
 }
 
-Images findImages(const string& vaultpath, const KindConfig& conf, bool all)
+Images findImages(const string& vaultpath, const KindConfig& conf, bool alsoInvalidImages)
 {
   Strings dirs;
   debugPrint("searching images in " + vaultpath);
   dirList(vaultpath, dirs);
 
+  string imgName = conf.getString("imageName");
+
   Images imageList;
   for (string dir : dirs)
     {
       FileName fn(dir);
-      string imgname = conf.getString("imageName");
-      if (startsWith(fn.getName(), imgname))
+      if (startsWith(fn.getName(), imgName))
         {
           debugPrint("Checking " + dir);
           Image image(dir);
 
-          if (all || image.valid)
+          if (alsoInvalidImages || image.valid)
             imageList.push_back(image);
         }
     }
+  // sort by name == sort by creation time
   if (imageList.size() > 1)
     sort(imageList.begin(), imageList.end());
   return imageList;
 }
 
 void listImageInfo(const string& vault,
-                   KindConfig conf /*Copy!*/ ,
+                   KindConfig conf /*Copy!*/,
                    const DateTime& imageTime,
                    const string& backupSet)
 {
@@ -333,7 +332,7 @@ void doBackup(const string& vault,
   if (!dryRun)
     {
       ofstream error(errorfile);
-      error << "failed" << endl;
+      error << "rsync not successfully completed" << endl;
       error.close();
     }
 
@@ -387,8 +386,8 @@ void doBackup(const string& vault,
       int rc;
       backupResult = localExec(rsyncCmd, rc, debug, imageFullName + "/rsync-log");
       if (rc == 0 ||  // "no error"
-          rc == 24 || // "vanished source files" (ignored)
-          rc == 6144) // workaround for wrong exit code ??!!
+          rc == 24 // "vanished source files" (ignored)
+         )
         {
           unlink(errorfile.c_str());
           double st = 0;
@@ -410,7 +409,7 @@ void doBackup(const string& vault,
 }
 
 bool backupVault(const string& vault,
-                 KindConfig conf /*Copy!*/ ,
+                 KindConfig conf /*Copy!*/,
                  const DateTime& imageTime,
                  bool fullImage,
                  const string& forcedBackupSet)
@@ -429,6 +428,9 @@ bool backupVault(const string& vault,
 
       bool backupNow = true;
 
+      if (conf.getString("path").empty()) // empty path string disables backup
+	backupNow = false;
+
       // existing images
       Images validImageList = findImages(vaultPath, conf, false);
       string currentSet = "expire"; // we are not using backupSets
@@ -439,7 +441,7 @@ bool backupVault(const string& vault,
       vector<SetRule> backupSetRule;
       int setRuleIdx = -1;
 
-      if (conf.getBool("useBackupSet"))
+      if (conf.getBool("useBackupSet") && backupNow)
         {
           readSetRules(conf, setIdx, backupSetRule);
           if (!setIdx.empty())
@@ -500,17 +502,23 @@ bool backupVault(const string& vault,
                   else
                     throw Exception("force backup of set " + forcedBackupSet, " set not exists");
                 }
+              if (conf.getBool("appendSetToImageName"))
+                imageFullName += "-" + currentSet;
             } // if (!setIdx.empty())
         } // (conf.hasKey("setRule"))
 
-      if (backupNow)
+      if (!quiet)
         {
-          verbosePrint("backup to \"" + imageFullName + "\"");
-          if (setRuleIdx >= 0 && !quiet)
-            cout << "  backup set is \"" << currentSet << "\"" << endl;
+          if (backupNow)
+            {
+              if (setRuleIdx >= 0)
+                cout << "  backup set \"" << currentSet << "\" to \"" << imageFullName << "\"" << endl;
+              else
+                cout << "  backup to \"" << imageFullName << "\"" << endl;
+            }
+          else
+            cout << "  no backup set needs update" << endl;
         }
-      else if (!quiet)
-        cout << "  no backup set needs update" << endl;
 
       if (backupNow)
         {
@@ -528,6 +536,7 @@ bool backupVault(const string& vault,
 
           if (!dryRun)
             {
+              // hard or soft link to last image path
               string lastPath = vaultPath + "/last";
               struct stat fstat;
 
@@ -570,7 +579,7 @@ bool backupVault(const string& vault,
               expireFile << currentSet << "-" << expireTime.getString('m') << endl;
               expireFile << rule << endl;
             }
-	  //  conf.warnUnused();
+          //  conf.warnUnused();
         }
       return backupNow;
     }
@@ -673,6 +682,7 @@ int main(int argc, char* argv[])
       // default-values
       conf.addString("imageName", "image");
       conf.addString("vaultConfigName", "kind/vault.conf");
+      conf.addString("vaultConfigName", "vault.conf");
       conf.addString("expireFailedImage", "3 days");
       conf.addString("expireRule", "* * * * 1 month");
       conf.addString("ping", "ping -c 1 -W 5 %host");
@@ -684,6 +694,7 @@ int main(int argc, char* argv[])
                      "find %path -type f -iname '*nobackup' -printf '%P\\\\n'");
       conf.addString("logSize", "");
       conf.addString("lastLink", "symLink");
+      conf.addString("appendSetToImageName", "false");
 
       if (listConfig)
         {
@@ -698,22 +709,22 @@ int main(int argc, char* argv[])
         throw Exception("read master configuration", "no banks defined");
 
       vector<string> vaults;
-      string groupname = "group_" + vault;
+      string groupname = "group_" + vault_or_group;
       if (conf.hasKey(groupname))
         {
           vaults = conf.getStrings(groupname);
-          vault.clear(); // no single vault but group
+          vault_or_group.clear(); // no single vault but group
         }
       else
-        vaults.push_back(vault);
+        vaults.push_back(vault_or_group);
 
       if (listConfig)
         {
           cout << "global config:" << endl;
           conf.print(".   ");
-          if (!vault.empty())
+          if (!vault_or_group.empty())
             {
-              readVaultConfig(vault, conf);
+              readVaultConfig(vault_or_group, conf);
               cout << "vault config:" << endl;
               conf.print(".   ");
             }
@@ -731,6 +742,16 @@ int main(int argc, char* argv[])
           exit(0);
         }
 
+      if (listVault)
+        {
+          sort(vaults.begin(), vaults.end());
+          for (string vault : vaults)
+            {
+              string vaultPath = findVault(vault);
+              cout << vaultPath << endl;
+            }
+          exit(0);
+        }
       // previous actions do not need locking
       lockFile = conf.getString("lockfile");
       createLock(lockFile);
@@ -738,6 +759,7 @@ int main(int argc, char* argv[])
       string logSizeFile = conf.getString("logSize");
       readSizes(logSizeFile);
 
+#if 0
       for (string vault : vaults)
         {
           if (doBackup)
@@ -746,6 +768,17 @@ int main(int argc, char* argv[])
           if (doExpire)
             expireVault(vault, conf, imageTime);
         }
+#endif
+      if (doBackup)
+        for (string vault : vaults)
+          {
+            if (backupVault(vault, conf, imageTime, fullImage, forcedBackupSet))
+              writeSizes(logSizeFile);
+          }
+
+      if (doExpire)
+        for (string vault : vaults)
+          expireVault(vault, conf, imageTime);
 
       if (!quiet)
         cout << DateTime::now().getString('h') << ": finished" << endl;

+ 1 - 1
src/stringtools.cpp

@@ -144,7 +144,7 @@ string getWord(const string& s, unsigned int& i)
   if (!isalpha(s[i]) && s[i] != '-' && s[i] != '_')
     throw Exception("getWord", "letter expected");
   string is;
-  while (i < s.size() && (isalpha(s[i]) || s[i] == '-' || s[i] == '_'))
+  while (i < s.size() && (isalnum(s[i]) || s[i] == '-' || s[i] == '_'))
     {
       is += s[i];
       ++i;