|
@@ -0,0 +1,1673 @@
|
|
|
|
+# 1 "kind.ag"
|
|
|
|
+#include <dirent.h>
|
|
|
|
+# 2 "kind.ag"
|
|
|
|
+#include <sys/stat.h>
|
|
|
|
+# 3 "kind.ag"
|
|
|
|
+#include <cstring>
|
|
|
|
+# 4 "kind.ag"
|
|
|
|
+#include <unistd.h>
|
|
|
|
+# 5 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 6 "kind.ag"
|
|
|
|
+#include <iostream>
|
|
|
|
+# 7 "kind.ag"
|
|
|
|
+#include <fstream>
|
|
|
|
+# 8 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 9 "kind.ag"
|
|
|
|
+#include <string>
|
|
|
|
+# 10 "kind.ag"
|
|
|
|
+#include <vector>
|
|
|
|
+# 11 "kind.ag"
|
|
|
|
+#include <set>
|
|
|
|
+# 12 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 13 "kind.ag"
|
|
|
|
+#include <algorithm>
|
|
|
|
+# 14 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 15 "kind.ag"
|
|
|
|
+#include "stringtools.h"
|
|
|
|
+# 16 "kind.ag"
|
|
|
|
+#include "Exception.h"
|
|
|
|
+# 17 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 18 "kind.ag"
|
|
|
|
+#include "DateTime.h"
|
|
|
|
+# 19 "kind.ag"
|
|
|
|
+#include "FileName.h"
|
|
|
|
+# 20 "kind.ag"
|
|
|
|
+#include "KindConfig.h"
|
|
|
|
+# 21 "kind.ag"
|
|
|
|
+#include "filetools.h"
|
|
|
|
+# 22 "kind.ag"
|
|
|
|
+#include "Lexer.h"
|
|
|
|
+# 23 "kind.ag"
|
|
|
|
+#include "rulecomp.h"
|
|
|
|
+# 24 "kind.ag"
|
|
|
|
+#include "Strings.h"
|
|
|
|
+# 25 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 26 "kind.ag"
|
|
|
|
+/*AppGen
|
|
|
|
+# 27 "kind.ag"
|
|
|
|
+ %% Beschreibung des Programmes:
|
|
|
|
+# 28 "kind.ag"
|
|
|
|
+ prog: archiving backup
|
|
|
|
+# 29 "kind.ag"
|
|
|
|
+ %% Beschreibung Parameter
|
|
|
|
+# 30 "kind.ag"
|
|
|
|
+ % symbolischerName, Art, Typ, Variablenname, Erklärung, Default-Wert
|
|
|
|
+# 31 "kind.ag"
|
|
|
|
+ para: vault_or_group, required, string, vault, Vault to backup
|
|
|
|
+# 32 "kind.ag"
|
|
|
|
+ %% Beschreibung der Optionen
|
|
|
|
+# 33 "kind.ag"
|
|
|
|
+ % kurz-Option, lang-Option, Typ, Variablenname, Erklärung, Default-Wert
|
|
|
|
+# 34 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 35 "kind.ag"
|
|
|
|
+ opt: f, full, void, fullImage, Force full image == initial backup, false
|
|
|
|
+# 36 "kind.ag"
|
|
|
|
+ opt: c, masterconfig, string, masterConfig, Master config file, ""
|
|
|
|
+# 37 "kind.ag"
|
|
|
|
+ opt2: if not given or empty kind looks for
|
|
|
|
+# 38 "kind.ag"
|
|
|
|
+ opt2: /etc/kind/master.conf
|
|
|
|
+# 39 "kind.ag"
|
|
|
|
+ opt2: /ffp/etc/kind/master.conf
|
|
|
|
+# 40 "kind.ag"
|
|
|
|
+ opt: B, backuponly, void, backupOnly, Only backup/no expire, false
|
|
|
|
+# 41 "kind.ag"
|
|
|
|
+ opt: E, expireonly, void, expireOnly, Only expire/no backup, false
|
|
|
|
+# 42 "kind.ag"
|
|
|
|
+ opt: D, dryrun, Void, dryRun, Dry run (no real backup), false
|
|
|
|
+# 43 "kind.ag"
|
|
|
|
+ opt: v, verbose, Void, verbose, Verbose, false
|
|
|
|
+# 44 "kind.ag"
|
|
|
|
+ opt: d, debug, Void, debug, Debug output of many data, false
|
|
|
|
+# 45 "kind.ag"
|
|
|
|
+ opt: q, quiet, Void, quiet, Be quiet - no messages, false
|
|
|
|
+# 46 "kind.ag"
|
|
|
|
+ opt: h, help, usage, ignored , This help
|
|
|
|
+# 47 "kind.ag"
|
|
|
|
+AppGen*/
|
|
|
|
+# 48 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 49 "kind.ag"
|
|
|
|
+using namespace std;
|
|
|
|
+# 50 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 51 "kind.ag"
|
|
|
|
+/*AppGen:Global*/
|
|
|
|
+#include <getopt.h>
|
|
|
|
+#include <string>
|
|
|
|
+#include <string>
|
|
|
|
+bool dryRun = false;
|
|
|
|
+bool verbose = false;
|
|
|
|
+bool debug = false;
|
|
|
|
+bool quiet = false;
|
|
|
|
+/*AppGen:GlobalEnd*/
|
|
|
|
+# 52 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 53 "kind.ag"
|
|
|
|
+vector<string> banks;
|
|
|
|
+# 54 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 55 "kind.ag"
|
|
|
|
+typedef pair<long int, long int> Sizes;
|
|
|
|
+# 56 "kind.ag"
|
|
|
|
+map<string, Sizes> sizes;
|
|
|
|
+# 57 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 58 "kind.ag"
|
|
|
|
+void verbosePrint(const string& text)
|
|
|
|
+# 59 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 60 "kind.ag"
|
|
|
|
+ if (verbose)
|
|
|
|
+# 61 "kind.ag"
|
|
|
|
+ cout << " " << text << endl;
|
|
|
|
+# 62 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 63 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 64 "kind.ag"
|
|
|
|
+void debugPrint(const string& text)
|
|
|
|
+# 65 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 66 "kind.ag"
|
|
|
|
+ if (verbose)
|
|
|
|
+# 67 "kind.ag"
|
|
|
|
+ cout << " " << text << endl;
|
|
|
|
+# 68 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 69 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 70 "kind.ag"
|
|
|
|
+void readMasterConfig(const string& fn, KindConfig& conf)
|
|
|
|
+# 71 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 72 "kind.ag"
|
|
|
|
+ verbosePrint("reading global config " + fn);
|
|
|
|
+# 73 "kind.ag"
|
|
|
|
+ conf.addFile(fn);
|
|
|
|
+# 74 "kind.ag"
|
|
|
|
+ banks = conf.getStrings("bank");
|
|
|
|
+# 75 "kind.ag"
|
|
|
|
+ if (banks.empty())
|
|
|
|
+# 76 "kind.ag"
|
|
|
|
+ throw Exception("read main config", "no banks defined");
|
|
|
|
+# 77 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 78 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 79 "kind.ag"
|
|
|
|
+string findVault(const string& v)
|
|
|
|
+# 80 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 81 "kind.ag"
|
|
|
|
+ bool found = false;
|
|
|
|
+# 82 "kind.ag"
|
|
|
|
+ FileName fn;
|
|
|
|
+# 83 "kind.ag"
|
|
|
|
+ fn.setName(v);
|
|
|
|
+# 84 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; !found && i < banks.size(); ++i)
|
|
|
|
+# 85 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 86 "kind.ag"
|
|
|
|
+ fn.setPath(banks[i]);
|
|
|
|
+# 87 "kind.ag"
|
|
|
|
+ if (dirExists(fn.getFileName()))
|
|
|
|
+# 88 "kind.ag"
|
|
|
|
+ found = true;
|
|
|
|
+# 89 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 90 "kind.ag"
|
|
|
|
+ if (!found)
|
|
|
|
+# 91 "kind.ag"
|
|
|
|
+ throw Exception("find vault", v + " not found");
|
|
|
|
+# 92 "kind.ag"
|
|
|
|
+ verbosePrint("using vault " + fn.getFileName());
|
|
|
|
+# 93 "kind.ag"
|
|
|
|
+ return fn.getFileName();
|
|
|
|
+# 94 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 95 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 96 "kind.ag"
|
|
|
|
+void readVaultConfig(const string& vaultConfigName, KindConfig& conf)
|
|
|
|
+# 97 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 98 "kind.ag"
|
|
|
|
+ FileName fn(vaultConfigName);
|
|
|
|
+# 99 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 100 "kind.ag"
|
|
|
|
+ verbosePrint("reading vault config " + fn.getFileName());
|
|
|
|
+# 101 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 102 "kind.ag"
|
|
|
|
+ conf.addFile(fn.getFileName());
|
|
|
|
+# 103 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 104 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 105 "kind.ag"
|
|
|
|
+string getImageName(const KindConfig& conf)
|
|
|
|
+# 106 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 107 "kind.ag"
|
|
|
|
+ bool nonPortable = false;
|
|
|
|
+# 108 "kind.ag"
|
|
|
|
+ string res = conf.getString("imageName");
|
|
|
|
+# 109 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; !nonPortable && i < res.size(); ++i)
|
|
|
|
+# 110 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 111 "kind.ag"
|
|
|
|
+ char c = res[i];
|
|
|
|
+# 112 "kind.ag"
|
|
|
|
+ if (!isalnum(c) && c != '.' && c != '_')
|
|
|
|
+# 113 "kind.ag"
|
|
|
|
+ nonPortable = true;
|
|
|
|
+# 114 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 115 "kind.ag"
|
|
|
|
+ if (nonPortable)
|
|
|
|
+# 116 "kind.ag"
|
|
|
|
+ throw Exception("getImageName", "Invalid character in image name " + res);
|
|
|
|
+# 117 "kind.ag"
|
|
|
|
+ return res;
|
|
|
|
+# 118 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 119 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 120 "kind.ag"
|
|
|
|
+bool isValidImage(const string& imageName)
|
|
|
|
+# 121 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 122 "kind.ag"
|
|
|
|
+ return dirExists(imageName) &&
|
|
|
|
+# 123 "kind.ag"
|
|
|
|
+ !fileExists(imageName + "/error") &&
|
|
|
|
+# 124 "kind.ag"
|
|
|
|
+ dirExists(imageName + "/tree");
|
|
|
|
+# 125 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 126 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 127 "kind.ag"
|
|
|
|
+Strings findValidImages(const string& vaultpath, const KindConfig& conf)
|
|
|
|
+# 128 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 129 "kind.ag"
|
|
|
|
+ Strings imageList;
|
|
|
|
+# 130 "kind.ag"
|
|
|
|
+ debugPrint("searching images in " + vaultpath);
|
|
|
|
+# 131 "kind.ag"
|
|
|
|
+ dirList(vaultpath, imageList);
|
|
|
|
+# 132 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 133 "kind.ag"
|
|
|
|
+ Strings validImageList;
|
|
|
|
+# 134 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < imageList.size(); ++i)
|
|
|
|
+# 135 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 136 "kind.ag"
|
|
|
|
+ FileName fn(imageList[i]);
|
|
|
|
+# 137 "kind.ag"
|
|
|
|
+ string imgname = getImageName(conf);
|
|
|
|
+# 138 "kind.ag"
|
|
|
|
+ int len = imgname.length();
|
|
|
|
+# 139 "kind.ag"
|
|
|
|
+ if (fn.getName().substr(0, len) == imgname)
|
|
|
|
+# 140 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 141 "kind.ag"
|
|
|
|
+ debugPrint("Checking " + imageList[i]);
|
|
|
|
+# 142 "kind.ag"
|
|
|
|
+ if (isValidImage(imageList[i]))
|
|
|
|
+# 143 "kind.ag"
|
|
|
|
+ validImageList.push_back(imageList[i]);
|
|
|
|
+# 144 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 145 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 146 "kind.ag"
|
|
|
|
+ if (validImageList.empty())
|
|
|
|
+# 147 "kind.ag"
|
|
|
|
+ throw Exception("Find reference", "No reference found");
|
|
|
|
+# 148 "kind.ag"
|
|
|
|
+ sort(validImageList.begin(), validImageList.end());
|
|
|
|
+# 149 "kind.ag"
|
|
|
|
+ return validImageList;
|
|
|
|
+# 150 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 151 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 152 "kind.ag"
|
|
|
|
+void backupVault(const string& vault,
|
|
|
|
+# 153 "kind.ag"
|
|
|
|
+ KindConfig conf /*Copy!*/ ,
|
|
|
|
+# 154 "kind.ag"
|
|
|
|
+ const DateTime& imageTime,
|
|
|
|
+# 155 "kind.ag"
|
|
|
|
+ bool fullImage)
|
|
|
|
+# 156 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 157 "kind.ag"
|
|
|
|
+ if (!quiet)
|
|
|
|
+# 158 "kind.ag"
|
|
|
|
+ cout << DateTime::now().getString('h') << ": Backup of vault " << vault << endl;
|
|
|
|
+# 159 "kind.ag"
|
|
|
|
+ try
|
|
|
|
+# 160 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 161 "kind.ag"
|
|
|
|
+ sizes[vault].second = 0; // nothing backed up yet
|
|
|
|
+# 162 "kind.ag"
|
|
|
|
+ string vaultpath = findVault(vault);
|
|
|
|
+# 163 "kind.ag"
|
|
|
|
+ const string& vaultConfigName = vaultpath + '/' + conf.getString("vaultConfigName");
|
|
|
|
+# 164 "kind.ag"
|
|
|
|
+ readVaultConfig(vaultConfigName, conf);
|
|
|
|
+# 165 "kind.ag"
|
|
|
|
+ if (debug)
|
|
|
|
+# 166 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 167 "kind.ag"
|
|
|
|
+ cout << "vault config:" << endl;
|
|
|
|
+# 168 "kind.ag"
|
|
|
|
+ conf.print();
|
|
|
|
+# 169 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 170 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 171 "kind.ag"
|
|
|
|
+ string imageName = getImageName(conf);
|
|
|
|
+# 172 "kind.ag"
|
|
|
|
+ if (!imageName.empty())
|
|
|
|
+# 173 "kind.ag"
|
|
|
|
+ imageName += '-';
|
|
|
|
+# 174 "kind.ag"
|
|
|
|
+ string imageFullName = vaultpath + "/" + imageName ;
|
|
|
|
+# 175 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 176 "kind.ag"
|
|
|
|
+ if (conf.getBool("longImageName"))
|
|
|
|
+# 177 "kind.ag"
|
|
|
|
+ imageFullName += imageTime.getString('m');
|
|
|
|
+# 178 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 179 "kind.ag"
|
|
|
|
+ imageFullName += imageTime.getString('s');
|
|
|
|
+# 180 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 181 "kind.ag"
|
|
|
|
+ verbosePrint("backup to \"" + imageFullName + "\"");
|
|
|
|
+# 182 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 183 "kind.ag"
|
|
|
|
+ // find reference image
|
|
|
|
+# 184 "kind.ag"
|
|
|
|
+ string referenceImage;
|
|
|
|
+# 185 "kind.ag"
|
|
|
|
+ if (!fullImage)
|
|
|
|
+# 186 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 187 "kind.ag"
|
|
|
|
+ Strings validImageList = findValidImages(vaultpath, conf);
|
|
|
|
+# 188 "kind.ag"
|
|
|
|
+ // last image is newest image
|
|
|
|
+# 189 "kind.ag"
|
|
|
|
+ referenceImage = validImageList.back();
|
|
|
|
+# 190 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 191 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 192 "kind.ag"
|
|
|
|
+ // create image path
|
|
|
|
+# 193 "kind.ag"
|
|
|
|
+ if (!dryRun)
|
|
|
|
+# 194 "kind.ag"
|
|
|
|
+ if (mkdir(imageFullName.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
|
|
|
|
+# 195 "kind.ag"
|
|
|
|
+ throw Exception("Create image", "failed to create " + imageFullName);
|
|
|
|
+# 196 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 197 "kind.ag"
|
|
|
|
+ // error message
|
|
|
|
+# 198 "kind.ag"
|
|
|
|
+ // we write an generic error message to mark backup as unsuccessful
|
|
|
|
+# 199 "kind.ag"
|
|
|
|
+ // will be deleted at successful end of rsync
|
|
|
|
+# 200 "kind.ag"
|
|
|
|
+ string errorfile = imageFullName + "/error";
|
|
|
|
+# 201 "kind.ag"
|
|
|
|
+ if (!dryRun)
|
|
|
|
+# 202 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 203 "kind.ag"
|
|
|
|
+ ofstream error(errorfile);
|
|
|
|
+# 204 "kind.ag"
|
|
|
|
+ error << "failed" << endl;
|
|
|
|
+# 205 "kind.ag"
|
|
|
|
+ error.close();
|
|
|
|
+# 206 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 207 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 208 "kind.ag"
|
|
|
|
+ string host;
|
|
|
|
+# 209 "kind.ag"
|
|
|
|
+ if (conf.hasKey("host"))
|
|
|
|
+# 210 "kind.ag"
|
|
|
|
+ host = conf.getString("host");
|
|
|
|
+# 211 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 212 "kind.ag"
|
|
|
|
+ string server;
|
|
|
|
+# 213 "kind.ag"
|
|
|
|
+ if (conf.hasKey("server"))
|
|
|
|
+# 214 "kind.ag"
|
|
|
|
+ server = conf.getString("server");
|
|
|
|
+# 215 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 216 "kind.ag"
|
|
|
|
+ if (!host.empty() && !server.empty())
|
|
|
|
+# 217 "kind.ag"
|
|
|
|
+ throw Exception("backupVault", "Cannot have host and server");
|
|
|
|
+# 218 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 219 "kind.ag"
|
|
|
|
+ string path = conf.getString("path");
|
|
|
|
+# 220 "kind.ag"
|
|
|
|
+ if (path.empty())
|
|
|
|
+# 221 "kind.ag"
|
|
|
|
+ throw Exception("rsync", "empty source path");
|
|
|
|
+# 222 "kind.ag"
|
|
|
|
+ if (path.back() != '/')
|
|
|
|
+# 223 "kind.ag"
|
|
|
|
+ path += '/';
|
|
|
|
+# 224 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 225 "kind.ag"
|
|
|
|
+ string rsyncCmd = "rsync -vrltH --delete --stats -D --numeric-ids ";
|
|
|
|
+# 226 "kind.ag"
|
|
|
|
+ if (!conf.getBool("ignorePermission"))
|
|
|
|
+# 227 "kind.ag"
|
|
|
|
+ rsyncCmd += "-pgo";
|
|
|
|
+# 228 "kind.ag"
|
|
|
|
+ vector<string> rso = conf.getStrings("rsyncOption");
|
|
|
|
+# 229 "kind.ag"
|
|
|
|
+ for (string opt : rso)
|
|
|
|
+# 230 "kind.ag"
|
|
|
|
+ rsyncCmd += opt + " ";
|
|
|
|
+# 231 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 232 "kind.ag"
|
|
|
|
+ if (!host.empty()) // shell mode
|
|
|
|
+# 233 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 234 "kind.ag"
|
|
|
|
+ // cout << "USING SHELLMODE '" << host << "'" << endl;
|
|
|
|
+# 235 "kind.ag"
|
|
|
|
+ string remoteShell = conf.getString("remoteShell");
|
|
|
|
+# 236 "kind.ag"
|
|
|
|
+ string userAtHost = conf.getString("user") + "@" +
|
|
|
|
+# 237 "kind.ag"
|
|
|
|
+ conf.getString("host");
|
|
|
|
+# 238 "kind.ag"
|
|
|
|
+ string rshCommand = remoteShell;
|
|
|
|
+# 239 "kind.ag"
|
|
|
|
+ if (remoteShell.empty())
|
|
|
|
+# 240 "kind.ag"
|
|
|
|
+ rshCommand = "ssh";
|
|
|
|
+# 241 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 242 "kind.ag"
|
|
|
|
+ rshCommand += " " + userAtHost;
|
|
|
|
+# 243 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 244 "kind.ag"
|
|
|
|
+ // excludes
|
|
|
|
+# 245 "kind.ag"
|
|
|
|
+ Strings excluded;
|
|
|
|
+# 246 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 247 "kind.ag"
|
|
|
|
+ string userExcludeCommand = conf.getString("userExcludeCommand");
|
|
|
|
+# 248 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 249 "kind.ag"
|
|
|
|
+ if (!userExcludeCommand.empty())
|
|
|
|
+# 250 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 251 "kind.ag"
|
|
|
|
+ replacePlaceHolder(userExcludeCommand, "%path", path);
|
|
|
|
+# 252 "kind.ag"
|
|
|
|
+ string excludeCommand = rshCommand + " " + userExcludeCommand;
|
|
|
|
+# 253 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 254 "kind.ag"
|
|
|
|
+ verbosePrint("searching for exclusions (" + excludeCommand + ")");
|
|
|
|
+# 255 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 256 "kind.ag"
|
|
|
|
+ int rc;
|
|
|
|
+# 257 "kind.ag"
|
|
|
|
+ excluded = myPopen(excludeCommand, rc, debug);
|
|
|
|
+# 258 "kind.ag"
|
|
|
|
+ if (rc > 0)
|
|
|
|
+# 259 "kind.ag"
|
|
|
|
+ throw Exception("Find exludes", "Search for excludes failed");
|
|
|
|
+# 260 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 261 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < excluded.size(); ++i)
|
|
|
|
+# 262 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 263 "kind.ag"
|
|
|
|
+ FileName fn(excluded[i]);
|
|
|
|
+# 264 "kind.ag"
|
|
|
|
+ excluded[i] = '/' + fn.getPath();
|
|
|
|
+# 265 "kind.ag"
|
|
|
|
+ debugPrint("Excluding: " + excluded[i]);
|
|
|
|
+# 266 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 267 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 268 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 269 "kind.ag"
|
|
|
|
+ string userExcludeFile = conf.getString("userExcludeFile");
|
|
|
|
+# 270 "kind.ag"
|
|
|
|
+ if (!userExcludeFile.empty())
|
|
|
|
+# 271 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 272 "kind.ag"
|
|
|
|
+ userExcludeFile = path + userExcludeFile;
|
|
|
|
+# 273 "kind.ag"
|
|
|
|
+ string getExcludeFileCommand = rshCommand;
|
|
|
|
+# 274 "kind.ag"
|
|
|
|
+ getExcludeFileCommand += " \" if [ -f '" + userExcludeFile + "' ]; then ";
|
|
|
|
+# 275 "kind.ag"
|
|
|
|
+ getExcludeFileCommand += " cat '" + userExcludeFile + "' ; fi \"";
|
|
|
|
+# 276 "kind.ag"
|
|
|
|
+ // cout << getExcludeFileCommand << endl;
|
|
|
|
+# 277 "kind.ag"
|
|
|
|
+ int rc;
|
|
|
|
+# 278 "kind.ag"
|
|
|
|
+ Strings excludes2 = myPopen(getExcludeFileCommand, rc, debug);
|
|
|
|
+# 279 "kind.ag"
|
|
|
|
+ if (rc == 0)
|
|
|
|
+# 280 "kind.ag"
|
|
|
|
+ excluded += excludes2;
|
|
|
|
+# 281 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 282 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 283 "kind.ag"
|
|
|
|
+ if (conf.hasKey("exclude"))
|
|
|
|
+# 284 "kind.ag"
|
|
|
|
+ excluded += conf.getStrings("exclude");
|
|
|
|
+# 285 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 286 "kind.ag"
|
|
|
|
+ if (!dryRun)
|
|
|
|
+# 287 "kind.ag"
|
|
|
|
+ strings2File(excluded, imageFullName + "/exclude");
|
|
|
|
+# 288 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 289 "kind.ag"
|
|
|
|
+ // rsync image
|
|
|
|
+# 290 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 291 "kind.ag"
|
|
|
|
+ if (!remoteShell.empty())
|
|
|
|
+# 292 "kind.ag"
|
|
|
|
+ rsyncCmd += " -e \'" + remoteShell + "\' ";
|
|
|
|
+# 293 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 294 "kind.ag"
|
|
|
|
+ rsyncCmd += "--exclude-from=" + imageFullName + "/exclude ";
|
|
|
|
+# 295 "kind.ag"
|
|
|
|
+ if (!referenceImage.empty())
|
|
|
|
+# 296 "kind.ag"
|
|
|
|
+ rsyncCmd += "--link-dest=" + referenceImage + "/tree ";
|
|
|
|
+# 297 "kind.ag"
|
|
|
|
+ rsyncCmd += userAtHost + ":" + path + " ";
|
|
|
|
+# 298 "kind.ag"
|
|
|
|
+ rsyncCmd += imageFullName + "/tree";
|
|
|
|
+# 299 "kind.ag"
|
|
|
|
+ } // shell mode
|
|
|
|
+# 300 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 301 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 302 "kind.ag"
|
|
|
|
+ // cout << "USING SERVERMODE" << endl;
|
|
|
|
+# 303 "kind.ag"
|
|
|
|
+ vector<string> excluded;
|
|
|
|
+# 304 "kind.ag"
|
|
|
|
+ if (conf.hasKey("exclude"))
|
|
|
|
+# 305 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 306 "kind.ag"
|
|
|
|
+ Strings excludes = conf.getStrings("exclude");
|
|
|
|
+# 307 "kind.ag"
|
|
|
|
+ for (string s : excludes)
|
|
|
|
+# 308 "kind.ag"
|
|
|
|
+ excluded.push_back(s);
|
|
|
|
+# 309 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 310 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 311 "kind.ag"
|
|
|
|
+ if (!dryRun)
|
|
|
|
+# 312 "kind.ag"
|
|
|
|
+ strings2File(excluded, imageFullName + "/exclude");
|
|
|
|
+# 313 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 314 "kind.ag"
|
|
|
|
+ rsyncCmd += "--exclude-from=" + imageFullName + "/exclude ";
|
|
|
|
+# 315 "kind.ag"
|
|
|
|
+ if (!referenceImage.empty())
|
|
|
|
+# 316 "kind.ag"
|
|
|
|
+ rsyncCmd += "--link-dest=" + referenceImage + "/tree ";
|
|
|
|
+# 317 "kind.ag"
|
|
|
|
+ rsyncCmd += conf.getString("server") + "::" + path + " ";
|
|
|
|
+# 318 "kind.ag"
|
|
|
|
+ rsyncCmd += imageFullName + "/tree";
|
|
|
|
+# 319 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 320 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 321 "kind.ag"
|
|
|
|
+ debugPrint("Action: " + rsyncCmd);
|
|
|
|
+# 322 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 323 "kind.ag"
|
|
|
|
+ vector<string> backupResult;
|
|
|
|
+# 324 "kind.ag"
|
|
|
|
+ if (!dryRun)
|
|
|
|
+# 325 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 326 "kind.ag"
|
|
|
|
+ verbosePrint("syncing (" + rsyncCmd + ")");
|
|
|
|
+# 327 "kind.ag"
|
|
|
|
+ int rc;
|
|
|
|
+# 328 "kind.ag"
|
|
|
|
+ backupResult = myPopen(rsyncCmd, rc, debug, imageFullName + "/rsync-log");
|
|
|
|
+# 329 "kind.ag"
|
|
|
|
+ // strings2File(backupResult, imageFullName + "/rsync-log");
|
|
|
|
+# 330 "kind.ag"
|
|
|
|
+ if (rc == 0 || rc == 24) // "no error" or "vanished source files" (ignored)
|
|
|
|
+# 331 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 332 "kind.ag"
|
|
|
|
+ unlink(errorfile.c_str());
|
|
|
|
+# 333 "kind.ag"
|
|
|
|
+ string lastLink = vaultpath + "/last";
|
|
|
|
+# 334 "kind.ag"
|
|
|
|
+ unlink(lastLink.c_str());
|
|
|
|
+# 335 "kind.ag"
|
|
|
|
+ symlink(imageFullName.c_str(), lastLink.c_str());
|
|
|
|
+# 336 "kind.ag"
|
|
|
|
+ long int st = 0;
|
|
|
|
+# 337 "kind.ag"
|
|
|
|
+ long int sc = 0;
|
|
|
|
+# 338 "kind.ag"
|
|
|
|
+ for (auto bl : backupResult)
|
|
|
|
+# 339 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 340 "kind.ag"
|
|
|
|
+ if (bl.substr(0, 15) == "Total file size")
|
|
|
|
+# 341 "kind.ag"
|
|
|
|
+ st = getNumber(bl);
|
|
|
|
+# 342 "kind.ag"
|
|
|
|
+ else if (bl.substr(0, 27) == "Total transferred file size")
|
|
|
|
+# 343 "kind.ag"
|
|
|
|
+ sc = getNumber(bl);
|
|
|
|
+# 344 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 345 "kind.ag"
|
|
|
|
+ // sizes[vault] = pair<long int, long int>(st, sc);
|
|
|
|
+# 346 "kind.ag"
|
|
|
|
+ sizes[vault] = Sizes(st, sc);
|
|
|
|
+# 347 "kind.ag"
|
|
|
|
+ // cout << vault << " " << st << " || " << sc << endl;
|
|
|
|
+# 348 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 349 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 350 "kind.ag"
|
|
|
|
+ throw Exception("Backup", "Failed to execute rsync");
|
|
|
|
+# 351 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 352 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 353 "kind.ag"
|
|
|
|
+ cout << "Not executing " << rsyncCmd << endl;
|
|
|
|
+# 354 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 355 "kind.ag"
|
|
|
|
+ catch (Exception ex)
|
|
|
|
+# 356 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 357 "kind.ag"
|
|
|
|
+ cerr << "Exception in vault " << vault << ": " << ex.what() << endl;
|
|
|
|
+# 358 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 359 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 360 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 361 "kind.ag"
|
|
|
|
+DateTime imageDate(const string& image)
|
|
|
|
+# 362 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 363 "kind.ag"
|
|
|
|
+ FileName fn(image);
|
|
|
|
+# 364 "kind.ag"
|
|
|
|
+ Strings ss;
|
|
|
|
+# 365 "kind.ag"
|
|
|
|
+ split(fn.getName(), ss, '-');
|
|
|
|
+# 366 "kind.ag"
|
|
|
|
+ if (ss.size() < 5)
|
|
|
|
+# 367 "kind.ag"
|
|
|
|
+ throw Exception("imageDate", "image date not available");
|
|
|
|
+# 368 "kind.ag"
|
|
|
|
+ int Y = stoi(ss[1]);
|
|
|
|
+# 369 "kind.ag"
|
|
|
|
+ int M = stoi(ss[2]);
|
|
|
|
+# 370 "kind.ag"
|
|
|
|
+ int D = stoi(ss[3]);
|
|
|
|
+# 371 "kind.ag"
|
|
|
|
+ int h = stoi(ss[4]);
|
|
|
|
+# 372 "kind.ag"
|
|
|
|
+ int m = 0, s = 0;
|
|
|
|
+# 373 "kind.ag"
|
|
|
|
+ if (ss.size() > 5) // longImageName
|
|
|
|
+# 374 "kind.ag"
|
|
|
|
+ m = stoi(ss[5]);
|
|
|
|
+# 375 "kind.ag"
|
|
|
|
+ if (ss.size() > 6)
|
|
|
|
+# 376 "kind.ag"
|
|
|
|
+ s = stoi(ss[6]);
|
|
|
|
+# 377 "kind.ag"
|
|
|
|
+ return DateTime(Y, M, D, h, m, s);
|
|
|
|
+# 378 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 379 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 380 "kind.ag"
|
|
|
|
+void parseRule(string rule,
|
|
|
|
+# 381 "kind.ag"
|
|
|
|
+ set<int>& M, set<int>& D, set<int>& W, set<int>& h,
|
|
|
|
+# 382 "kind.ag"
|
|
|
|
+ time_t& exptime)
|
|
|
|
+# 383 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 384 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < rule.size(); ++i)
|
|
|
|
+# 385 "kind.ag"
|
|
|
|
+ rule[i] = tolower(rule[i]);
|
|
|
|
+# 386 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 387 "kind.ag"
|
|
|
|
+ substitute(rule, ' ', ',');
|
|
|
|
+# 388 "kind.ag"
|
|
|
|
+ reduceToOne(rule, ',');
|
|
|
|
+# 389 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 390 "kind.ag"
|
|
|
|
+ // rule = hour wday mday month <exptime>
|
|
|
|
+# 391 "kind.ag"
|
|
|
|
+ Lexer p(rule);
|
|
|
|
+# 392 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 393 "kind.ag"
|
|
|
|
+ h = getValues(p, 0, 23); // hour
|
|
|
|
+# 394 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 395 "kind.ag"
|
|
|
|
+ p.expect(',');
|
|
|
|
+# 396 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 397 "kind.ag"
|
|
|
|
+ W = getValues(p, 0, 7, 1); // wday
|
|
|
|
+# 398 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 399 "kind.ag"
|
|
|
|
+ p.expect(',');
|
|
|
|
+# 400 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 401 "kind.ag"
|
|
|
|
+ D = getValues(p, 1, 31); // day of month
|
|
|
|
+# 402 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 403 "kind.ag"
|
|
|
|
+ p.expect(',');
|
|
|
|
+# 404 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 405 "kind.ag"
|
|
|
|
+ M = getValues(p, 1, 12, 2); // month
|
|
|
|
+# 406 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 407 "kind.ag"
|
|
|
|
+#if 0
|
|
|
|
+# 408 "kind.ag"
|
|
|
|
+ // debug-output
|
|
|
|
+# 409 "kind.ag"
|
|
|
|
+ cout << "hour: ";
|
|
|
|
+# 410 "kind.ag"
|
|
|
|
+ for (int i : h)
|
|
|
|
+# 411 "kind.ag"
|
|
|
|
+ cout << i << " ";
|
|
|
|
+# 412 "kind.ag"
|
|
|
|
+ cout << endl;
|
|
|
|
+# 413 "kind.ag"
|
|
|
|
+ cout << "wday: ";
|
|
|
|
+# 414 "kind.ag"
|
|
|
|
+ for (int i : W)
|
|
|
|
+# 415 "kind.ag"
|
|
|
|
+ cout << i << " ";
|
|
|
|
+# 416 "kind.ag"
|
|
|
|
+ cout << endl;
|
|
|
|
+# 417 "kind.ag"
|
|
|
|
+ cout << "mday: ";
|
|
|
|
+# 418 "kind.ag"
|
|
|
|
+ for (int i : D)
|
|
|
|
+# 419 "kind.ag"
|
|
|
|
+ cout << i << " ";
|
|
|
|
+# 420 "kind.ag"
|
|
|
|
+ cout << endl;
|
|
|
|
+# 421 "kind.ag"
|
|
|
|
+ cout << "month: ";
|
|
|
|
+# 422 "kind.ag"
|
|
|
|
+ for (int i : M)
|
|
|
|
+# 423 "kind.ag"
|
|
|
|
+ cout << i << " ";
|
|
|
|
+# 424 "kind.ag"
|
|
|
|
+ cout << endl;
|
|
|
|
+# 425 "kind.ag"
|
|
|
|
+#endif
|
|
|
|
+# 426 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 427 "kind.ag"
|
|
|
|
+ string ts = p.getAll();
|
|
|
|
+# 428 "kind.ag"
|
|
|
|
+ substitute(ts, ',', ' ');
|
|
|
|
+# 429 "kind.ag"
|
|
|
|
+ exptime = stot(ts);
|
|
|
|
+# 430 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 431 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 432 "kind.ag"
|
|
|
|
+int removeDir(const string& path)
|
|
|
|
+# 433 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 434 "kind.ag"
|
|
|
|
+ debugPrint("removeDir " + path);
|
|
|
|
+# 435 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 436 "kind.ag"
|
|
|
|
+ DIR* d = opendir(path.c_str());
|
|
|
|
+# 437 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 438 "kind.ag"
|
|
|
|
+ int r = -1;
|
|
|
|
+# 439 "kind.ag"
|
|
|
|
+ if (d)
|
|
|
|
+# 440 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 441 "kind.ag"
|
|
|
|
+ struct dirent* p;
|
|
|
|
+# 442 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 443 "kind.ag"
|
|
|
|
+ r = 0;
|
|
|
|
+# 444 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 445 "kind.ag"
|
|
|
|
+ while (!r && (p = readdir(d)))
|
|
|
|
+# 446 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 447 "kind.ag"
|
|
|
|
+ int r2 = 0;
|
|
|
|
+# 448 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 449 "kind.ag"
|
|
|
|
+ string fn = p->d_name;
|
|
|
|
+# 450 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 451 "kind.ag"
|
|
|
|
+ if (fn != "." && fn != "..")
|
|
|
|
+# 452 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 453 "kind.ag"
|
|
|
|
+ fn = path + "/" + fn;
|
|
|
|
+# 454 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 455 "kind.ag"
|
|
|
|
+ debugPrint("-- " + fn);
|
|
|
|
+# 456 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 457 "kind.ag"
|
|
|
|
+ struct stat statbuf;
|
|
|
|
+# 458 "kind.ag"
|
|
|
|
+ if (lstat(fn.c_str(), &statbuf) == 0)
|
|
|
|
+# 459 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 460 "kind.ag"
|
|
|
|
+ if (S_ISLNK(statbuf.st_mode))
|
|
|
|
+# 461 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 462 "kind.ag"
|
|
|
|
+ debugPrint("Remove link " + fn);
|
|
|
|
+# 463 "kind.ag"
|
|
|
|
+ r2 = unlink(fn.c_str());
|
|
|
|
+# 464 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 465 "kind.ag"
|
|
|
|
+ else if (S_ISDIR(statbuf.st_mode))
|
|
|
|
+# 466 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 467 "kind.ag"
|
|
|
|
+ debugPrint("Remove dir " + fn);
|
|
|
|
+# 468 "kind.ag"
|
|
|
|
+ r2 = removeDir(fn);
|
|
|
|
+# 469 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 470 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 471 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 472 "kind.ag"
|
|
|
|
+ debugPrint("Remove file " + fn);
|
|
|
|
+# 473 "kind.ag"
|
|
|
|
+ r2 = unlink(fn.c_str());
|
|
|
|
+# 474 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 475 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 476 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 477 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 478 "kind.ag"
|
|
|
|
+ cout << "stat(" << fn << ") failed" << endl;
|
|
|
|
+# 479 "kind.ag"
|
|
|
|
+ // we assume "file" here
|
|
|
|
+# 480 "kind.ag"
|
|
|
|
+ r2 = unlink(fn.c_str());
|
|
|
|
+# 481 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 482 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 483 "kind.ag"
|
|
|
|
+ r = r2;
|
|
|
|
+# 484 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 485 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 486 "kind.ag"
|
|
|
|
+ closedir(d);
|
|
|
|
+# 487 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 488 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 489 "kind.ag"
|
|
|
|
+ if (r == 0)
|
|
|
|
+# 490 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 491 "kind.ag"
|
|
|
|
+ debugPrint("Remove Dir itself " + path);
|
|
|
|
+# 492 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 493 "kind.ag"
|
|
|
|
+ r = rmdir(path.c_str());
|
|
|
|
+# 494 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 495 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 496 "kind.ag"
|
|
|
|
+ return r;
|
|
|
|
+# 497 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 498 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 499 "kind.ag"
|
|
|
|
+#if 0
|
|
|
|
+# 500 "kind.ag"
|
|
|
|
+int removeDir(const string& dname)
|
|
|
|
+# 501 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 502 "kind.ag"
|
|
|
|
+ int rc = 0;
|
|
|
|
+# 503 "kind.ag"
|
|
|
|
+ if (!dryRun)
|
|
|
|
+# 504 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 505 "kind.ag"
|
|
|
|
+ Strings files;
|
|
|
|
+# 506 "kind.ag"
|
|
|
|
+ // subdirectories
|
|
|
|
+# 507 "kind.ag"
|
|
|
|
+ dirList(dname, files);
|
|
|
|
+# 508 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < files.size(); ++i)
|
|
|
|
+# 509 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 510 "kind.ag"
|
|
|
|
+ debugPrint("Remove dir " + files[i]);
|
|
|
|
+# 511 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < files.size(); ++i)
|
|
|
|
+# 512 "kind.ag"
|
|
|
|
+ rc += removeDir(files[i]);
|
|
|
|
+# 513 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 514 "kind.ag"
|
|
|
|
+ files.clear();
|
|
|
|
+# 515 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 516 "kind.ag"
|
|
|
|
+ // files in directory
|
|
|
|
+# 517 "kind.ag"
|
|
|
|
+ fileList(dname, files);
|
|
|
|
+# 518 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < files.size(); ++i)
|
|
|
|
+# 519 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 520 "kind.ag"
|
|
|
|
+ debugPrint("unlink " + files[i]);
|
|
|
|
+# 521 "kind.ag"
|
|
|
|
+ if (!dryRun)
|
|
|
|
+# 522 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 523 "kind.ag"
|
|
|
|
+ if (unlink(files[i].c_str()) != 0)
|
|
|
|
+# 524 "kind.ag"
|
|
|
|
+ rc++;
|
|
|
|
+# 525 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 526 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 527 "kind.ag"
|
|
|
|
+ debugPrint("rmdir " + dname);
|
|
|
|
+# 528 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 529 "kind.ag"
|
|
|
|
+ // directory
|
|
|
|
+# 530 "kind.ag"
|
|
|
|
+ if (rmdir(dname.c_str()) != 0)
|
|
|
|
+# 531 "kind.ag"
|
|
|
|
+ rc++;
|
|
|
|
+# 532 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 533 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 534 "kind.ag"
|
|
|
|
+ return rc;
|
|
|
|
+# 535 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 536 "kind.ag"
|
|
|
|
+#endif
|
|
|
|
+# 537 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 538 "kind.ag"
|
|
|
|
+void expireVault(const string& vault, KindConfig conf, DateTime now)
|
|
|
|
+# 539 "kind.ag"
|
|
|
|
+{
|
|
|
|
+# 540 "kind.ag"
|
|
|
|
+ if (!quiet)
|
|
|
|
+# 541 "kind.ag"
|
|
|
|
+ cout << DateTime::now().getString('h') << ": Expiring images in vault " << vault << endl;
|
|
|
|
+# 542 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 543 "kind.ag"
|
|
|
|
+ string vaultpath = findVault(vault);
|
|
|
|
+# 544 "kind.ag"
|
|
|
|
+ debugPrint("searching images in " + vaultpath);
|
|
|
|
+# 545 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 546 "kind.ag"
|
|
|
|
+ const string& vaultConfigName = vaultpath + '/' + conf.getString("vaultConfigName");
|
|
|
|
+# 547 "kind.ag"
|
|
|
|
+ readVaultConfig(vaultConfigName, conf);
|
|
|
|
+# 548 "kind.ag"
|
|
|
|
+ if (debug)
|
|
|
|
+# 549 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 550 "kind.ag"
|
|
|
|
+ cout << "vault config:" << endl;
|
|
|
|
+# 551 "kind.ag"
|
|
|
|
+ conf.print();
|
|
|
|
+# 552 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 553 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 554 "kind.ag"
|
|
|
|
+ Strings dirlist; // list of subdirectories
|
|
|
|
+# 555 "kind.ag"
|
|
|
|
+ dirList(vaultpath, dirlist);
|
|
|
|
+# 556 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 557 "kind.ag"
|
|
|
|
+ Strings validImages;
|
|
|
|
+# 558 "kind.ag"
|
|
|
|
+ Strings invalidImages;
|
|
|
|
+# 559 "kind.ag"
|
|
|
|
+ string imgname = getImageName(conf);
|
|
|
|
+# 560 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 561 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < dirlist.size(); ++i)
|
|
|
|
+# 562 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 563 "kind.ag"
|
|
|
|
+ FileName fn(dirlist[i]);
|
|
|
|
+# 564 "kind.ag"
|
|
|
|
+ if (startsWith(fn.getName(), imgname)) // dir is image ?
|
|
|
|
+# 565 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 566 "kind.ag"
|
|
|
|
+ debugPrint(dirlist[i]);
|
|
|
|
+# 567 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 568 "kind.ag"
|
|
|
|
+ DateTime t = imageDate(dirlist[i]);
|
|
|
|
+# 569 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 570 "kind.ag"
|
|
|
|
+ if (t != now) // ignore just created image
|
|
|
|
+# 571 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 572 "kind.ag"
|
|
|
|
+ if (!isValidImage(dirlist[i])) // invalid image?
|
|
|
|
+# 573 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 574 "kind.ag"
|
|
|
|
+ invalidImages.push_back(dirlist[i]);
|
|
|
|
+# 575 "kind.ag"
|
|
|
|
+ debugPrint("- invalid image");
|
|
|
|
+# 576 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 577 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 578 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 579 "kind.ag"
|
|
|
|
+ validImages.push_back(dirlist[i]);
|
|
|
|
+# 580 "kind.ag"
|
|
|
|
+ debugPrint("- valid image");
|
|
|
|
+# 581 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 582 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 583 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 584 "kind.ag"
|
|
|
|
+ debugPrint("- current image - ignored");
|
|
|
|
+# 585 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 586 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 587 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 588 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < invalidImages.size(); ++i)
|
|
|
|
+# 589 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 590 "kind.ag"
|
|
|
|
+ try
|
|
|
|
+# 591 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 592 "kind.ag"
|
|
|
|
+ DateTime t = imageDate(invalidImages[i]);
|
|
|
|
+# 593 "kind.ag"
|
|
|
|
+ DateTime expireTime = t + stot(conf.getString("expireFailedImage"));
|
|
|
|
+# 594 "kind.ag"
|
|
|
|
+ if (debug)
|
|
|
|
+# 595 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 596 "kind.ag"
|
|
|
|
+ cout << "image: " << t.getString('h') << " expire: " << expireTime.getString('h') << endl;
|
|
|
|
+# 597 "kind.ag"
|
|
|
|
+ cout << " now: " << now.getString('h') << endl;
|
|
|
|
+# 598 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 599 "kind.ag"
|
|
|
|
+ if (expireTime < now)
|
|
|
|
+# 600 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 601 "kind.ag"
|
|
|
|
+ if (!quiet)
|
|
|
|
+# 602 "kind.ag"
|
|
|
|
+ cout << " removing invalid image " << invalidImages[i] << endl;
|
|
|
|
+# 603 "kind.ag"
|
|
|
|
+ if (removeDir(invalidImages[i]) != 0)
|
|
|
|
+# 604 "kind.ag"
|
|
|
|
+ cout << "Error removing " << invalidImages[i] << endl;
|
|
|
|
+# 605 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 606 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 607 "kind.ag"
|
|
|
|
+ catch (Exception ex)
|
|
|
|
+# 608 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 609 "kind.ag"
|
|
|
|
+ cerr << "Exception: " << ex.what() << endl;
|
|
|
|
+# 610 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 611 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 612 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 613 "kind.ag"
|
|
|
|
+ sort(validImages.begin(), validImages.end()); // lexicographical order == temporal order
|
|
|
|
+# 614 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0;
|
|
|
|
+# 615 "kind.ag"
|
|
|
|
+ i < validImages.size() - 1; // never expire latest image
|
|
|
|
+# 616 "kind.ag"
|
|
|
|
+ ++i)
|
|
|
|
+# 617 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 618 "kind.ag"
|
|
|
|
+ try
|
|
|
|
+# 619 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 620 "kind.ag"
|
|
|
|
+ DateTime imageTime = imageDate(validImages[i]);
|
|
|
|
+# 621 "kind.ag"
|
|
|
|
+ DateTime expireTime = DateTime::now() + 100; // don't expire if no rule found
|
|
|
|
+# 622 "kind.ag"
|
|
|
|
+ Strings expireRules = conf.getStrings("expireRule");
|
|
|
|
+# 623 "kind.ag"
|
|
|
|
+ int ruleNr = 0;
|
|
|
|
+# 624 "kind.ag"
|
|
|
|
+ for (unsigned int k = 0; k < expireRules.size(); ++k)
|
|
|
|
+# 625 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 626 "kind.ag"
|
|
|
|
+ debugPrint("Checking rule " + expireRules[k]);
|
|
|
|
+# 627 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 628 "kind.ag"
|
|
|
|
+ set<int> M, D, W, h;
|
|
|
|
+# 629 "kind.ag"
|
|
|
|
+ set<int> Y, m, s;
|
|
|
|
+# 630 "kind.ag"
|
|
|
|
+ time_t expirePeriod;
|
|
|
|
+# 631 "kind.ag"
|
|
|
|
+ parseRule(expireRules[k], M, D, W, h, expirePeriod);
|
|
|
|
+# 632 "kind.ag"
|
|
|
|
+ // cout << M << " " << D << " " << W << " " << h << " " << expirePeriod << endl;
|
|
|
|
+# 633 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 634 "kind.ag"
|
|
|
|
+ if (imageTime.match(Y, M, D, W, h, m, s))
|
|
|
|
+# 635 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 636 "kind.ag"
|
|
|
|
+ debugPrint("match");
|
|
|
|
+# 637 "kind.ag"
|
|
|
|
+ expireTime = imageTime + expirePeriod;
|
|
|
|
+# 638 "kind.ag"
|
|
|
|
+ ruleNr = k;
|
|
|
|
+# 639 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 640 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 641 "kind.ag"
|
|
|
|
+ if (debug)
|
|
|
|
+# 642 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 643 "kind.ag"
|
|
|
|
+ cout << "image: " << imageTime.getString('h') << " expire: " << expireTime.getString('h') << endl;
|
|
|
|
+# 644 "kind.ag"
|
|
|
|
+ cout << " now: " << now.getString('h') << endl;
|
|
|
|
+# 645 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 646 "kind.ag"
|
|
|
|
+ if (now > expireTime)
|
|
|
|
+# 647 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 648 "kind.ag"
|
|
|
|
+ if (!quiet)
|
|
|
|
+# 649 "kind.ag"
|
|
|
|
+ cout << "removing " << validImages[i] << " rule=" << expireRules[ruleNr] << endl;
|
|
|
|
+# 650 "kind.ag"
|
|
|
|
+ removeDir(validImages[i]);
|
|
|
|
+# 651 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 652 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 653 "kind.ag"
|
|
|
|
+ catch (Exception ex)
|
|
|
|
+# 654 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 655 "kind.ag"
|
|
|
|
+ cerr << "Exception: " << ex.what() << endl;
|
|
|
|
+# 656 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 657 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 658 "kind.ag"
|
|
|
|
+}
|
|
|
|
+# 659 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 660 "kind.ag"
|
|
|
|
+/*AppGen:Main*/
|
|
|
|
+string ag_programName;
|
|
|
|
+
|
|
|
|
+void usage()
|
|
|
|
+{
|
|
|
|
+ cout << ag_programName << " - archiving backup" << endl;
|
|
|
|
+ cout << "Aufruf:" << endl;
|
|
|
|
+ cout << ag_programName << " [<options>] vault_or_group " << endl;
|
|
|
|
+ cout << " vault_or_group - Vault to backup" << endl;
|
|
|
|
+ cout << "Optionen:" << endl;
|
|
|
|
+ cout << " -f --full Force full image == initial backup (default: false)" << endl;
|
|
|
|
+ cout << " -c --masterconfig Master config file (default: \"\")" << endl;
|
|
|
|
+ cout << " if not given or empty kind looks for" << endl;
|
|
|
|
+ cout << " /etc/kind/master.conf" << endl;
|
|
|
|
+ cout << " /ffp/etc/kind/master.conf" << endl;
|
|
|
|
+ cout << " -B --backuponly Only backup/no expire (default: false)" << endl;
|
|
|
|
+ cout << " -E --expireonly Only expire/no backup (default: false)" << endl;
|
|
|
|
+ cout << " -D --dryrun Dry run (no real backup) (default: false)" << endl;
|
|
|
|
+ cout << " -v --verbose Verbose (default: false)" << endl;
|
|
|
|
+ cout << " -d --debug Debug output of many data (default: false)" << endl;
|
|
|
|
+ cout << " -q --quiet Be quiet - no messages (default: false)" << endl;
|
|
|
|
+ cout << " -h --help This help" << endl;
|
|
|
|
+ exit(1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void error(const string& msg)
|
|
|
|
+{
|
|
|
|
+ cout << endl << ag_programName << " - error: " << msg << endl << endl;
|
|
|
|
+ usage();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int ptoi(const char* para)
|
|
|
|
+{
|
|
|
|
+ char* end;
|
|
|
|
+ int res = strtol(para, &end, 10);
|
|
|
|
+ if (end == para)
|
|
|
|
+ error(string("no int: ") + para);
|
|
|
|
+ if (*end != 0)
|
|
|
|
+ error(string("garbage in int: ") + para);
|
|
|
|
+ return res;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+double ptod(const char* para)
|
|
|
|
+{
|
|
|
|
+ char* end;
|
|
|
|
+ double res = strtod(para, &end);
|
|
|
|
+ if (end == para)
|
|
|
|
+ error(string("no double: ") + para);
|
|
|
|
+ if (*end != 0)
|
|
|
|
+ error(string("garbage in double: ") + para);
|
|
|
|
+ return res;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int main(int argc, char** argv)
|
|
|
|
+{
|
|
|
|
+ bool fullImage = false;
|
|
|
|
+ string masterConfig = "";
|
|
|
|
+ bool backupOnly = false;
|
|
|
|
+ bool expireOnly = false;
|
|
|
|
+
|
|
|
|
+ string vault = "";
|
|
|
|
+ static struct option ag_long_options[] =
|
|
|
|
+ {
|
|
|
|
+ {"full", no_argument, 0, 'f' },
|
|
|
|
+ {"masterconfig", required_argument, 0, 'c' },
|
|
|
|
+ {"backuponly", no_argument, 0, 'B' },
|
|
|
|
+ {"expireonly", no_argument, 0, 'E' },
|
|
|
|
+ {"dryrun", no_argument, 0, 'D' },
|
|
|
|
+ {"verbose", no_argument, 0, 'v' },
|
|
|
|
+ {"debug", no_argument, 0, 'd' },
|
|
|
|
+ {"quiet", no_argument, 0, 'q' },
|
|
|
|
+ {"help", no_argument, 0, 'h' },
|
|
|
|
+ {0, 0, 0, 0 }
|
|
|
|
+ };
|
|
|
|
+ ag_programName = argv[0];
|
|
|
|
+ int rc;
|
|
|
|
+ opterr = 0;
|
|
|
|
+ while ((rc = getopt_long(argc, argv, ":fc:BEDvdqh", ag_long_options, NULL)) >= 0)
|
|
|
|
+ {
|
|
|
|
+ switch (rc)
|
|
|
|
+ {
|
|
|
|
+ case '?':
|
|
|
|
+ error("Unknown option");
|
|
|
|
+ break;
|
|
|
|
+ case ':':
|
|
|
|
+ error("Expecting option parameter");
|
|
|
|
+ break;
|
|
|
|
+ case 'f':
|
|
|
|
+ fullImage = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'c':
|
|
|
|
+ masterConfig = optarg;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'B':
|
|
|
|
+ backupOnly = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'E':
|
|
|
|
+ expireOnly = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'D':
|
|
|
|
+ dryRun = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'v':
|
|
|
|
+ verbose = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'd':
|
|
|
|
+ debug = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'q':
|
|
|
|
+ quiet = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'h':
|
|
|
|
+ usage();
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ error("error in options");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (optind < argc)
|
|
|
|
+ vault = argv[optind++];
|
|
|
|
+ else error("Parameter vault_or_group needed");
|
|
|
|
+
|
|
|
|
+ /*AppGen:MainEnd*/
|
|
|
|
+# 664 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 665 "kind.ag"
|
|
|
|
+ int exitCode = 0;
|
|
|
|
+# 666 "kind.ag"
|
|
|
|
+ string lockFile;
|
|
|
|
+# 667 "kind.ag"
|
|
|
|
+ try
|
|
|
|
+# 668 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 669 "kind.ag"
|
|
|
|
+ if (debug)
|
|
|
|
+# 670 "kind.ag"
|
|
|
|
+ verbose = true;
|
|
|
|
+# 671 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 672 "kind.ag"
|
|
|
|
+ KindConfig conf;
|
|
|
|
+# 673 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 674 "kind.ag"
|
|
|
|
+ // default-values
|
|
|
|
+# 675 "kind.ag"
|
|
|
|
+ conf.add("imageName", "image");
|
|
|
|
+# 676 "kind.ag"
|
|
|
|
+ conf.add("vaultConfigName", "kind/vault.conf");
|
|
|
|
+# 677 "kind.ag"
|
|
|
|
+ conf.add("expireFailedImage", "3 days");
|
|
|
|
+# 678 "kind.ag"
|
|
|
|
+ conf.add("expireRule", "* * * * 1 month");
|
|
|
|
+# 679 "kind.ag"
|
|
|
|
+ conf.add("rsyncOption", ""); // no additional rsync option
|
|
|
|
+# 680 "kind.ag"
|
|
|
|
+ conf.add("remoteShell", "");
|
|
|
|
+# 681 "kind.ag"
|
|
|
|
+ conf.add("lockfile", "/var/lock/kind");
|
|
|
|
+# 682 "kind.ag"
|
|
|
|
+ conf.add("userExcludeFile", "nobackup.list");
|
|
|
|
+# 683 "kind.ag"
|
|
|
|
+ conf.add("userExcludeCommand",
|
|
|
|
+# 684 "kind.ag"
|
|
|
|
+ "find %path -type f -iname '*nobackup' -printf '%P\\\\n'");
|
|
|
|
+# 685 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 686 "kind.ag"
|
|
|
|
+ conf.add("logSize", "");
|
|
|
|
+# 687 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 688 "kind.ag"
|
|
|
|
+ if (!masterConfig.empty())
|
|
|
|
+# 689 "kind.ag"
|
|
|
|
+ readMasterConfig(masterConfig, conf);
|
|
|
|
+# 690 "kind.ag"
|
|
|
|
+ else if (fileExists("/etc/kind/master.conf"))
|
|
|
|
+# 691 "kind.ag"
|
|
|
|
+ readMasterConfig("etc/kind/master.conf", conf);
|
|
|
|
+# 692 "kind.ag"
|
|
|
|
+ else if (fileExists("/ffp/etc/kind/master.conf"))
|
|
|
|
+# 693 "kind.ag"
|
|
|
|
+ readMasterConfig("/ffp/etc/kind/master.conf", conf);
|
|
|
|
+# 694 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 695 "kind.ag"
|
|
|
|
+ throw Exception("MasterConfig", "no file");
|
|
|
|
+# 696 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 697 "kind.ag"
|
|
|
|
+ if (debug)
|
|
|
|
+# 698 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 699 "kind.ag"
|
|
|
|
+ cout << "global config:" << endl;
|
|
|
|
+# 700 "kind.ag"
|
|
|
|
+ conf.print();
|
|
|
|
+# 701 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 702 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 703 "kind.ag"
|
|
|
|
+ lockFile = conf.getString("lockfile");
|
|
|
|
+# 704 "kind.ag"
|
|
|
|
+ createLock(lockFile);
|
|
|
|
+# 705 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 706 "kind.ag"
|
|
|
|
+ DateTime imageTime = DateTime::now();
|
|
|
|
+# 707 "kind.ag"
|
|
|
|
+ string logSizeFile = conf.getString("logSize");
|
|
|
|
+# 708 "kind.ag"
|
|
|
|
+ if (!logSizeFile.empty() && fileExists(logSizeFile))
|
|
|
|
+# 709 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 710 "kind.ag"
|
|
|
|
+ vector<string> ss;
|
|
|
|
+# 711 "kind.ag"
|
|
|
|
+ file2Strings(logSizeFile, ss);
|
|
|
|
+# 712 "kind.ag"
|
|
|
|
+ for (auto s : ss)
|
|
|
|
+# 713 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 714 "kind.ag"
|
|
|
|
+ unsigned int i = 0;
|
|
|
|
+# 715 "kind.ag"
|
|
|
|
+ string v = getWord(s, i);
|
|
|
|
+# 716 "kind.ag"
|
|
|
|
+ long int s1 = getLongInt(s, i);
|
|
|
|
+# 717 "kind.ag"
|
|
|
|
+ long int s2 = getLongInt(s, i);
|
|
|
|
+# 718 "kind.ag"
|
|
|
|
+ sizes[v] = Sizes(s1, s2);
|
|
|
|
+# 719 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 720 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 721 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 722 "kind.ag"
|
|
|
|
+ vector<string> vaults;
|
|
|
|
+# 723 "kind.ag"
|
|
|
|
+ string groupname = "group_" + vault;
|
|
|
|
+# 724 "kind.ag"
|
|
|
|
+ if (conf.hasKey(groupname))
|
|
|
|
+# 725 "kind.ag"
|
|
|
|
+ vaults = conf.getStrings(groupname);
|
|
|
|
+# 726 "kind.ag"
|
|
|
|
+ else
|
|
|
|
+# 727 "kind.ag"
|
|
|
|
+ vaults.push_back(vault);
|
|
|
|
+# 728 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 729 "kind.ag"
|
|
|
|
+ if (!expireOnly)
|
|
|
|
+# 730 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < vaults.size(); ++i)
|
|
|
|
+# 731 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 732 "kind.ag"
|
|
|
|
+ backupVault(vaults[i], conf, imageTime, fullImage);
|
|
|
|
+# 733 "kind.ag"
|
|
|
|
+ if (!logSizeFile.empty())
|
|
|
|
+# 734 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 735 "kind.ag"
|
|
|
|
+ Strings st;
|
|
|
|
+# 736 "kind.ag"
|
|
|
|
+ for (auto s : sizes)
|
|
|
|
+# 737 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 738 "kind.ag"
|
|
|
|
+ string h = s.first + " " + to_string(s.second.first) + " " + to_string(s.second.second);
|
|
|
|
+# 739 "kind.ag"
|
|
|
|
+ st.push_back(h);
|
|
|
|
+# 740 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 741 "kind.ag"
|
|
|
|
+ strings2File(st, logSizeFile);
|
|
|
|
+# 742 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 743 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 744 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 745 "kind.ag"
|
|
|
|
+ if (!backupOnly)
|
|
|
|
+# 746 "kind.ag"
|
|
|
|
+ for (unsigned int i = 0; i < vaults.size(); ++i)
|
|
|
|
+# 747 "kind.ag"
|
|
|
|
+ expireVault(vaults[i], conf, imageTime);
|
|
|
|
+# 748 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 749 "kind.ag"
|
|
|
|
+ if (!quiet)
|
|
|
|
+# 750 "kind.ag"
|
|
|
|
+ cout << DateTime::now().getString('h') << ": finished" << endl;
|
|
|
|
+# 751 "kind.ag"
|
|
|
|
+
|
|
|
|
+# 752 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 753 "kind.ag"
|
|
|
|
+ catch (const Exception& ex)
|
|
|
|
+# 754 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 755 "kind.ag"
|
|
|
|
+ cerr << "Exception: " << ex.what() << endl;
|
|
|
|
+# 756 "kind.ag"
|
|
|
|
+ exitCode = 1;
|
|
|
|
+# 757 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 758 "kind.ag"
|
|
|
|
+ catch (const char* msg)
|
|
|
|
+# 759 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 760 "kind.ag"
|
|
|
|
+ cerr << "Exception(char*): " << msg << endl;
|
|
|
|
+# 761 "kind.ag"
|
|
|
|
+ exitCode = 1;
|
|
|
|
+# 762 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 763 "kind.ag"
|
|
|
|
+ catch (const string& msg)
|
|
|
|
+# 764 "kind.ag"
|
|
|
|
+ {
|
|
|
|
+# 765 "kind.ag"
|
|
|
|
+ cerr << "Exception(string): " << msg << endl;
|
|
|
|
+# 766 "kind.ag"
|
|
|
|
+ exitCode = 1;
|
|
|
|
+# 767 "kind.ag"
|
|
|
|
+ }
|
|
|
|
+# 768 "kind.ag"
|
|
|
|
+ removeLock(lockFile);
|
|
|
|
+# 769 "kind.ag"
|
|
|
|
+ return exitCode;
|
|
|
|
+# 770 "kind.ag"
|
|
|
|
+}
|