19 Commits 9d7bf95bfa ... c995a01394

Author SHA1 Message Date
  Wolfgang Ortmann c995a01394 reformatted 8 years ago
  Wolfgang Ortmann 250145db6c Better representation of exceptions. 8 years ago
  Wolfgang Ortmann 66f620d2a3 Update README.md 8 years ago
  Wolfgang Ortmann facc577c1f Merge branch 'master' of github.com:OWeh55/kind 8 years ago
  Wolfgang Ortmann 54a4e29791 support for big files (stat) 8 years ago
  Wolfgang Ortmann 25c9faa326 reworked "usage" 8 years ago
  Wolfgang Ortmann 724b4d31ba no backup if path is empty 8 years ago
  Wolfgang Ortmann 59e508a6fe formatting and error reporting 8 years ago
  Wolfgang Ortmann bbebd885e3 fixed error reporting with popen/pclose 8 years ago
  Wolfgang Ortmann c00a298061 *_Exception_* 9 years ago
  Wolfgang Ortmann 173a653cae adde rule for temporary files 9 years ago
  Wolfgang Ortmann b08762263b created .gitignore 9 years ago
  Wolfgang Ortmann dc0e459107 options 9 years ago
  Wolfgang Ortmann c184508ef7 makefile rule for kind_static fixed 9 years ago
  Wolfgang Ortmann 316c7cb925 -V listing of vault path added 9 years ago
  Wolfgang Ortmann afb3238283 static binary rebuild 9 years ago
  Wolfgang Ortmann 0c2de796e1 formatting 9 years ago
  Wolfgang Ortmann dc535f3b19 usage corrected, formatted 9 years ago
  Wolfgang Ortmann 5446d502cc added extended search for (default) config files: 9 years ago
17 changed files with 117 additions and 83 deletions
  1. 8 0
      .gitignore
  2. 1 1
      README.md
  3. BIN
      bin/kind
  4. 1 16
      src/DateTime.cpp
  5. 10 10
      src/DateTime.h
  6. 3 4
      src/FileName.cpp
  7. 1 2
      src/Image.cpp
  8. 14 0
      src/KindConfig.cpp
  9. 2 0
      src/KindConfig.h
  10. 3 5
      src/Lexer.cpp
  11. 1 1
      src/Makefile
  12. 0 2
      src/Strings.h
  13. 7 2
      src/excludetools.cpp
  14. 9 2
      src/filetools.cpp
  15. 54 37
      src/kind.ag
  16. 2 0
      src/kind.h
  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
+*~

+ 1 - 1
README.md

@@ -54,7 +54,7 @@ least the bank:
 ```
 - Create one or more subdirectories of the bank as "vault" for the backups
 - Create a subdirectory kind in each vault directory
-- Create a vault config files /[bank]/[vault]/kind/vault.conf, containing
+- Create a vault config file /[bank]/[vault]/kind/vault.conf, containing
 ```
     host=[client host]
 

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
-

+ 1 - 2
src/Image.cpp

@@ -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;
 }

+ 14 - 0
src/KindConfig.cpp

@@ -51,6 +51,20 @@ 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);

+ 2 - 0
src/KindConfig.h

@@ -5,6 +5,7 @@
 #include <string>
 #include "Strings.h"
 #include "stringtools.h"
+#include "filetools.h"
 
 class KindConfig
 {
@@ -13,6 +14,7 @@ public:
   KindConfig(const std::string& fn);
 
   void addFile(const std::string& fn);
+  int addOneFile(const std::vector<std::string>& fns);
 
   void addString(const std::string& key, const std::string& 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

+ 7 - 2
src/excludetools.cpp

@@ -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;
 }
-

+ 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;
 }

+ 54 - 37
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)
@@ -161,10 +160,14 @@ 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
 
@@ -251,7 +254,7 @@ Images findImages(const string& vaultpath, const KindConfig& conf, bool alsoInva
 }
 
 void listImageInfo(const string& vault,
-                   KindConfig conf /*Copy!*/ ,
+                   KindConfig conf /*Copy!*/,
                    const DateTime& imageTime,
                    const string& backupSet)
 {
@@ -329,7 +332,7 @@ void doBackup(const string& vault,
   if (!dryRun)
     {
       ofstream error(errorfile);
-      error << "failed" << endl;
+      error << "rsync not successfully completed" << endl;
       error.close();
     }
 
@@ -383,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;
@@ -406,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)
@@ -425,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
@@ -435,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())
@@ -579,7 +585,7 @@ bool backupVault(const string& vault,
     }
   catch (Exception ex)
     {
-      cerr << "Exception in vault " << vault << ": " << ex.what() << endl;
+      cerr << EXCEPTION + " in vault " << vault << ": " << ex.what() << endl;
       return false;
     }
 }
@@ -642,7 +648,7 @@ void expireVault(const string& vault, KindConfig conf, DateTime now)
                 }
               catch (Exception ex)
                 {
-                  cerr << "Exception: " << ex.what() << endl;
+                  cerr << EXCEPTION + ": " << ex.what() << endl;
                 }
             }
         }
@@ -676,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");
@@ -702,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(".   ");
             }
@@ -735,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);
@@ -769,17 +786,17 @@ int main(int argc, char* argv[])
     }
   catch (const Exception& ex)
     {
-      cerr << "Exception: " << ex.what() << endl;
+      cerr << EXCEPTION + ": " << ex.what() << endl;
       exitCode = 1;
     }
   catch (const char* msg)
     {
-      cerr << "Exception(char*): " << msg << endl;
+      cerr <<  EXCEPTION + ": " << msg << endl;
       exitCode = 1;
     }
   catch (const string& msg)
     {
-      cerr << "Exception(string): " << msg << endl;
+      cerr <<  EXCEPTION + ": " << msg << endl;
       exitCode = 1;
     }
   removeLock(lockFile);

+ 2 - 0
src/kind.h

@@ -11,4 +11,6 @@ void verbosePrint(const std::string& text);
 
 void debugPrint(const std::string& text);
 
+const std::string EXCEPTION = "###  EXCEPTION  ###";
+
 #endif

+ 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;