kind.cpp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520
  1. # 1 "kind.ag"
  2. #include <dirent.h>
  3. # 2 "kind.ag"
  4. #include <sys/stat.h>
  5. # 3 "kind.ag"
  6. #include <cstring>
  7. # 4 "kind.ag"
  8. #include <unistd.h>
  9. # 5 "kind.ag"
  10. # 6 "kind.ag"
  11. #include <iostream>
  12. # 7 "kind.ag"
  13. #include <fstream>
  14. # 8 "kind.ag"
  15. # 9 "kind.ag"
  16. #include <string>
  17. # 10 "kind.ag"
  18. #include <vector>
  19. # 11 "kind.ag"
  20. #include <set>
  21. # 12 "kind.ag"
  22. # 13 "kind.ag"
  23. #include <algorithm>
  24. # 14 "kind.ag"
  25. # 15 "kind.ag"
  26. #include "stringtools.h"
  27. # 16 "kind.ag"
  28. #include "Exception.h"
  29. # 17 "kind.ag"
  30. # 18 "kind.ag"
  31. #include "DateTime.h"
  32. # 19 "kind.ag"
  33. #include "Strings.h"
  34. # 20 "kind.ag"
  35. #include "FileName.h"
  36. # 21 "kind.ag"
  37. # 22 "kind.ag"
  38. #include "KindConfig.h"
  39. # 23 "kind.ag"
  40. #include "filetools.h"
  41. # 24 "kind.ag"
  42. #include "Lexer.h"
  43. # 25 "kind.ag"
  44. #include "rulecomp.h"
  45. # 26 "kind.ag"
  46. # 27 "kind.ag"
  47. #include "expiretools.h"
  48. # 28 "kind.ag"
  49. # 29 "kind.ag"
  50. /*AppGen
  51. # 30 "kind.ag"
  52. %% Beschreibung des Programmes:
  53. # 31 "kind.ag"
  54. prog: archiving backup
  55. # 32 "kind.ag"
  56. %% Beschreibung Parameter
  57. # 33 "kind.ag"
  58. % symbolischerName, Art, Typ, Variablenname, Erklärung, Default-Wert
  59. # 34 "kind.ag"
  60. para: vault_or_group, required, string, vault, Vault to backup
  61. # 35 "kind.ag"
  62. %% Beschreibung der Optionen
  63. # 36 "kind.ag"
  64. % kurz-Option, lang-Option, Typ, Variablenname, Erklärung, Default-Wert
  65. # 37 "kind.ag"
  66. # 38 "kind.ag"
  67. opt: f, full, void, fullImage, Force full image == initial backup, false
  68. # 39 "kind.ag"
  69. opt: c, masterconfig, string, masterConfig, Master config file, ""
  70. # 40 "kind.ag"
  71. opt2: if not given or empty kind looks for
  72. # 41 "kind.ag"
  73. opt2: /etc/kind/master.conf
  74. # 42 "kind.ag"
  75. opt2: /ffp/etc/kind/master.conf
  76. # 43 "kind.ag"
  77. opt: B, backuponly, void, backupOnly, Only backup/no expire, false
  78. # 44 "kind.ag"
  79. opt: E, expireonly, void, expireOnly, Only expire/no backup, false
  80. # 45 "kind.ag"
  81. opt: D, dryrun, Void, dryRun, Dry run (no real backup), false
  82. # 46 "kind.ag"
  83. opt: C, listconfig, void, listConfig, Show configuration, false
  84. # 47 "kind.ag"
  85. opt: v, verbose, Void, verbose, Verbose, false
  86. # 48 "kind.ag"
  87. opt: d, debug, Void, debug, Debug output of many data, false
  88. # 49 "kind.ag"
  89. opt: q, quiet, Void, quiet, Be quiet - no messages, false
  90. # 50 "kind.ag"
  91. opt: h, help, usage, ignored , This help
  92. # 51 "kind.ag"
  93. AppGen*/
  94. # 52 "kind.ag"
  95. # 53 "kind.ag"
  96. using namespace std;
  97. # 54 "kind.ag"
  98. # 55 "kind.ag"
  99. /*AppGen:Global*/
  100. #include <getopt.h>
  101. #include <string>
  102. #include <string>
  103. bool dryRun = false;
  104. bool verbose = false;
  105. bool debug = false;
  106. bool quiet = false;
  107. /*AppGen:GlobalEnd*/
  108. # 56 "kind.ag"
  109. # 57 "kind.ag"
  110. void createExpireFile(const string& image, const KindConfig& conf, string& rule);
  111. # 58 "kind.ag"
  112. # 59 "kind.ag"
  113. Strings banks;
  114. # 60 "kind.ag"
  115. # 61 "kind.ag"
  116. typedef pair<long int, long int> Sizes;
  117. # 62 "kind.ag"
  118. map<string, Sizes> sizes;
  119. # 63 "kind.ag"
  120. # 64 "kind.ag"
  121. void verbosePrint(const string& text)
  122. # 65 "kind.ag"
  123. {
  124. # 66 "kind.ag"
  125. if (verbose)
  126. # 67 "kind.ag"
  127. cout << " " << text << endl;
  128. # 68 "kind.ag"
  129. }
  130. # 69 "kind.ag"
  131. # 70 "kind.ag"
  132. void debugPrint(const string& text)
  133. # 71 "kind.ag"
  134. {
  135. # 72 "kind.ag"
  136. if (verbose)
  137. # 73 "kind.ag"
  138. cout << " " << text << endl;
  139. # 74 "kind.ag"
  140. }
  141. # 75 "kind.ag"
  142. # 76 "kind.ag"
  143. void readMasterConfig1(const string& fn, KindConfig& conf)
  144. # 77 "kind.ag"
  145. {
  146. # 78 "kind.ag"
  147. verbosePrint("reading master config " + fn);
  148. # 79 "kind.ag"
  149. conf.addFile(fn);
  150. # 80 "kind.ag"
  151. }
  152. # 81 "kind.ag"
  153. # 82 "kind.ag"
  154. void readMasterConfig(const string& fn, KindConfig& conf)
  155. # 83 "kind.ag"
  156. {
  157. # 84 "kind.ag"
  158. if (!fn.empty()) // master config given by user on commandline
  159. # 85 "kind.ag"
  160. readMasterConfig1(fn, conf);
  161. # 86 "kind.ag"
  162. else if (fileExists("/etc/kind/master.conf"))
  163. # 87 "kind.ag"
  164. readMasterConfig1("/etc/kind/master.conf", conf);
  165. # 88 "kind.ag"
  166. else if (fileExists("/ffp/etc/kind/master.conf"))
  167. # 89 "kind.ag"
  168. readMasterConfig1("/ffp/etc/kind/master.conf", conf);
  169. # 90 "kind.ag"
  170. else
  171. # 91 "kind.ag"
  172. throw Exception("MasterConfig", "no file");
  173. # 92 "kind.ag"
  174. }
  175. # 93 "kind.ag"
  176. # 94 "kind.ag"
  177. string findVault(const string& v)
  178. # 95 "kind.ag"
  179. {
  180. # 96 "kind.ag"
  181. bool found = false;
  182. # 97 "kind.ag"
  183. FileName fn;
  184. # 98 "kind.ag"
  185. fn.setName(v);
  186. # 99 "kind.ag"
  187. for (unsigned int i = 0; !found && i < banks.size(); ++i)
  188. # 100 "kind.ag"
  189. {
  190. # 101 "kind.ag"
  191. fn.setPath(banks[i]);
  192. # 102 "kind.ag"
  193. if (dirExists(fn.getFileName()))
  194. # 103 "kind.ag"
  195. found = true;
  196. # 104 "kind.ag"
  197. }
  198. # 105 "kind.ag"
  199. if (!found)
  200. # 106 "kind.ag"
  201. throw Exception("find vault", v + " not found");
  202. # 107 "kind.ag"
  203. verbosePrint("using vault " + fn.getFileName());
  204. # 108 "kind.ag"
  205. return fn.getFileName();
  206. # 109 "kind.ag"
  207. }
  208. # 110 "kind.ag"
  209. # 111 "kind.ag"
  210. void readVaultConfig(const string& vault, KindConfig& conf)
  211. # 112 "kind.ag"
  212. {
  213. # 113 "kind.ag"
  214. string vaultpath = findVault(vault);
  215. # 114 "kind.ag"
  216. const string& vaultConfigName = vaultpath + '/' + conf.getString("vaultConfigName");
  217. # 115 "kind.ag"
  218. verbosePrint("reading vault config:");
  219. # 116 "kind.ag"
  220. verbosePrint(" " + vaultConfigName);
  221. # 117 "kind.ag"
  222. conf.addFile(vaultConfigName);
  223. # 118 "kind.ag"
  224. }
  225. # 119 "kind.ag"
  226. # 120 "kind.ag"
  227. string getImageName(const KindConfig& conf)
  228. # 121 "kind.ag"
  229. {
  230. # 122 "kind.ag"
  231. bool nonPortable = false;
  232. # 123 "kind.ag"
  233. string res = conf.getString("imageName");
  234. # 124 "kind.ag"
  235. for (unsigned int i = 0; !nonPortable && i < res.size(); ++i)
  236. # 125 "kind.ag"
  237. {
  238. # 126 "kind.ag"
  239. char c = res[i];
  240. # 127 "kind.ag"
  241. if (!isalnum(c) && c != '.' && c != '_')
  242. # 128 "kind.ag"
  243. nonPortable = true;
  244. # 129 "kind.ag"
  245. }
  246. # 130 "kind.ag"
  247. if (nonPortable)
  248. # 131 "kind.ag"
  249. throw Exception("getImageName", "Invalid character in image name " + res);
  250. # 132 "kind.ag"
  251. return res;
  252. # 133 "kind.ag"
  253. }
  254. # 134 "kind.ag"
  255. # 135 "kind.ag"
  256. bool isValidImage(const string& imageName)
  257. # 136 "kind.ag"
  258. {
  259. # 137 "kind.ag"
  260. return dirExists(imageName) &&
  261. # 138 "kind.ag"
  262. !fileExists(imageName + "/error") &&
  263. # 139 "kind.ag"
  264. dirExists(imageName + "/tree");
  265. # 140 "kind.ag"
  266. }
  267. # 141 "kind.ag"
  268. # 142 "kind.ag"
  269. Strings findValidImages(const string& vaultpath, const KindConfig& conf)
  270. # 143 "kind.ag"
  271. {
  272. # 144 "kind.ag"
  273. Strings imageList;
  274. # 145 "kind.ag"
  275. debugPrint("searching images in " + vaultpath);
  276. # 146 "kind.ag"
  277. dirList(vaultpath, imageList);
  278. # 147 "kind.ag"
  279. # 148 "kind.ag"
  280. Strings validImageList;
  281. # 149 "kind.ag"
  282. for (unsigned int i = 0; i < imageList.size(); ++i)
  283. # 150 "kind.ag"
  284. {
  285. # 151 "kind.ag"
  286. FileName fn(imageList[i]);
  287. # 152 "kind.ag"
  288. string imgname = getImageName(conf);
  289. # 153 "kind.ag"
  290. int len = imgname.length();
  291. # 154 "kind.ag"
  292. if (fn.getName().substr(0, len) == imgname)
  293. # 155 "kind.ag"
  294. {
  295. # 156 "kind.ag"
  296. debugPrint("Checking " + imageList[i]);
  297. # 157 "kind.ag"
  298. if (isValidImage(imageList[i]))
  299. # 158 "kind.ag"
  300. validImageList.push_back(imageList[i]);
  301. # 159 "kind.ag"
  302. }
  303. # 160 "kind.ag"
  304. }
  305. # 161 "kind.ag"
  306. if (validImageList.empty())
  307. # 162 "kind.ag"
  308. throw Exception("Find reference", "No reference found");
  309. # 163 "kind.ag"
  310. sort(validImageList.begin(), validImageList.end());
  311. # 164 "kind.ag"
  312. return validImageList;
  313. # 165 "kind.ag"
  314. }
  315. # 166 "kind.ag"
  316. # 167 "kind.ag"
  317. void backupVault(const string& vault,
  318. # 168 "kind.ag"
  319. KindConfig conf /*Copy!*/ ,
  320. # 169 "kind.ag"
  321. const DateTime& imageTime,
  322. # 170 "kind.ag"
  323. bool fullImage)
  324. # 171 "kind.ag"
  325. {
  326. # 172 "kind.ag"
  327. if (!quiet)
  328. # 173 "kind.ag"
  329. cout << DateTime::now().getString('h') << ": Backup of vault " << vault << endl;
  330. # 174 "kind.ag"
  331. try
  332. # 175 "kind.ag"
  333. {
  334. # 176 "kind.ag"
  335. sizes[vault].second = 0; // nothing backed up yet
  336. # 177 "kind.ag"
  337. # 178 "kind.ag"
  338. readVaultConfig(vault, conf);
  339. # 179 "kind.ag"
  340. # 180 "kind.ag"
  341. string vaultpath = findVault(vault);
  342. # 181 "kind.ag"
  343. # 182 "kind.ag"
  344. string imageName = getImageName(conf);
  345. # 183 "kind.ag"
  346. if (!imageName.empty())
  347. # 184 "kind.ag"
  348. imageName += '-';
  349. # 185 "kind.ag"
  350. string imageFullName = vaultpath + "/" + imageName ;
  351. # 186 "kind.ag"
  352. # 187 "kind.ag"
  353. if (conf.getBool("longImageName"))
  354. # 188 "kind.ag"
  355. imageFullName += imageTime.getString('m');
  356. # 189 "kind.ag"
  357. else
  358. # 190 "kind.ag"
  359. imageFullName += imageTime.getString('s');
  360. # 191 "kind.ag"
  361. # 192 "kind.ag"
  362. verbosePrint("backup to \"" + imageFullName + "\"");
  363. # 193 "kind.ag"
  364. # 194 "kind.ag"
  365. // find reference image
  366. # 195 "kind.ag"
  367. string referenceImage;
  368. # 196 "kind.ag"
  369. if (!fullImage)
  370. # 197 "kind.ag"
  371. {
  372. # 198 "kind.ag"
  373. Strings validImageList = findValidImages(vaultpath, conf);
  374. # 199 "kind.ag"
  375. // last image is newest image
  376. # 200 "kind.ag"
  377. referenceImage = validImageList.back();
  378. # 201 "kind.ag"
  379. }
  380. # 202 "kind.ag"
  381. # 203 "kind.ag"
  382. // create image path
  383. # 204 "kind.ag"
  384. if (!dryRun)
  385. # 205 "kind.ag"
  386. if (mkdir(imageFullName.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
  387. # 206 "kind.ag"
  388. throw Exception("Create image", "failed to create " + imageFullName);
  389. # 207 "kind.ag"
  390. # 208 "kind.ag"
  391. // error message
  392. # 209 "kind.ag"
  393. // we write an generic error message to mark backup as unsuccessful
  394. # 210 "kind.ag"
  395. // will be deleted at successful end of rsync
  396. # 211 "kind.ag"
  397. string errorfile = imageFullName + "/error";
  398. # 212 "kind.ag"
  399. if (!dryRun)
  400. # 213 "kind.ag"
  401. {
  402. # 214 "kind.ag"
  403. ofstream error(errorfile);
  404. # 215 "kind.ag"
  405. error << "failed" << endl;
  406. # 216 "kind.ag"
  407. error.close();
  408. # 217 "kind.ag"
  409. }
  410. # 218 "kind.ag"
  411. # 219 "kind.ag"
  412. string host;
  413. # 220 "kind.ag"
  414. if (conf.hasKey("host"))
  415. # 221 "kind.ag"
  416. host = conf.getString("host");
  417. # 222 "kind.ag"
  418. # 223 "kind.ag"
  419. string server;
  420. # 224 "kind.ag"
  421. if (conf.hasKey("server"))
  422. # 225 "kind.ag"
  423. server = conf.getString("server");
  424. # 226 "kind.ag"
  425. # 227 "kind.ag"
  426. if (!host.empty() && !server.empty())
  427. # 228 "kind.ag"
  428. throw Exception("backupVault", "Cannot have host and server");
  429. # 229 "kind.ag"
  430. # 230 "kind.ag"
  431. string path = conf.getString("path");
  432. # 231 "kind.ag"
  433. if (path.empty())
  434. # 232 "kind.ag"
  435. throw Exception("rsync", "empty source path");
  436. # 233 "kind.ag"
  437. if (path.back() != '/')
  438. # 234 "kind.ag"
  439. path += '/';
  440. # 235 "kind.ag"
  441. # 236 "kind.ag"
  442. string rsyncCmd = "rsync -vrltH --delete --stats -D --numeric-ids ";
  443. # 237 "kind.ag"
  444. if (!conf.getBool("ignorePermission"))
  445. # 238 "kind.ag"
  446. rsyncCmd += "-pgo";
  447. # 239 "kind.ag"
  448. vector<string> rso = conf.getStrings("rsyncOption");
  449. # 240 "kind.ag"
  450. for (string opt : rso)
  451. # 241 "kind.ag"
  452. rsyncCmd += opt + " ";
  453. # 242 "kind.ag"
  454. # 243 "kind.ag"
  455. if (!host.empty()) // shell mode
  456. # 244 "kind.ag"
  457. {
  458. # 245 "kind.ag"
  459. // cout << "USING SHELLMODE '" << host << "'" << endl;
  460. # 246 "kind.ag"
  461. string remoteShell = conf.getString("remoteShell");
  462. # 247 "kind.ag"
  463. string userAtHost = conf.getString("user") + "@" +
  464. # 248 "kind.ag"
  465. conf.getString("host");
  466. # 249 "kind.ag"
  467. string rshCommand = remoteShell;
  468. # 250 "kind.ag"
  469. if (remoteShell.empty())
  470. # 251 "kind.ag"
  471. rshCommand = "ssh";
  472. # 252 "kind.ag"
  473. # 253 "kind.ag"
  474. rshCommand += " " + userAtHost;
  475. # 254 "kind.ag"
  476. # 255 "kind.ag"
  477. // excludes
  478. # 256 "kind.ag"
  479. Strings excluded;
  480. # 257 "kind.ag"
  481. # 258 "kind.ag"
  482. string userExcludeCommand = conf.getString("userExcludeCommand");
  483. # 259 "kind.ag"
  484. # 260 "kind.ag"
  485. if (!userExcludeCommand.empty())
  486. # 261 "kind.ag"
  487. {
  488. # 262 "kind.ag"
  489. replacePlaceHolder(userExcludeCommand, "%path", path);
  490. # 263 "kind.ag"
  491. string excludeCommand = rshCommand + " " + userExcludeCommand;
  492. # 264 "kind.ag"
  493. # 265 "kind.ag"
  494. verbosePrint("searching for exclusions (" + excludeCommand + ")");
  495. # 266 "kind.ag"
  496. # 267 "kind.ag"
  497. int rc;
  498. # 268 "kind.ag"
  499. excluded = myPopen(excludeCommand, rc, debug);
  500. # 269 "kind.ag"
  501. if (rc > 0)
  502. # 270 "kind.ag"
  503. throw Exception("Find exludes", "Search for excludes failed");
  504. # 271 "kind.ag"
  505. # 272 "kind.ag"
  506. for (unsigned int i = 0; i < excluded.size(); ++i)
  507. # 273 "kind.ag"
  508. {
  509. # 274 "kind.ag"
  510. FileName fn(excluded[i]);
  511. # 275 "kind.ag"
  512. excluded[i] = '/' + fn.getPath();
  513. # 276 "kind.ag"
  514. debugPrint("Excluding: " + excluded[i]);
  515. # 277 "kind.ag"
  516. }
  517. # 278 "kind.ag"
  518. }
  519. # 279 "kind.ag"
  520. # 280 "kind.ag"
  521. string userExcludeFile = conf.getString("userExcludeFile");
  522. # 281 "kind.ag"
  523. if (!userExcludeFile.empty())
  524. # 282 "kind.ag"
  525. {
  526. # 283 "kind.ag"
  527. userExcludeFile = path + userExcludeFile;
  528. # 284 "kind.ag"
  529. string getExcludeFileCommand = rshCommand;
  530. # 285 "kind.ag"
  531. getExcludeFileCommand += " \" if [ -f '" + userExcludeFile + "' ]; then ";
  532. # 286 "kind.ag"
  533. getExcludeFileCommand += " cat '" + userExcludeFile + "' ; fi \"";
  534. # 287 "kind.ag"
  535. // cout << getExcludeFileCommand << endl;
  536. # 288 "kind.ag"
  537. int rc;
  538. # 289 "kind.ag"
  539. Strings excludes2 = myPopen(getExcludeFileCommand, rc, debug);
  540. # 290 "kind.ag"
  541. if (rc == 0)
  542. # 291 "kind.ag"
  543. excluded += excludes2;
  544. # 292 "kind.ag"
  545. }
  546. # 293 "kind.ag"
  547. # 294 "kind.ag"
  548. if (conf.hasKey("exclude"))
  549. # 295 "kind.ag"
  550. excluded += conf.getStrings("exclude");
  551. # 296 "kind.ag"
  552. # 297 "kind.ag"
  553. if (!dryRun)
  554. # 298 "kind.ag"
  555. strings2File(excluded, imageFullName + "/exclude");
  556. # 299 "kind.ag"
  557. # 300 "kind.ag"
  558. // rsync image
  559. # 301 "kind.ag"
  560. # 302 "kind.ag"
  561. if (!remoteShell.empty())
  562. # 303 "kind.ag"
  563. rsyncCmd += " -e \'" + remoteShell + "\' ";
  564. # 304 "kind.ag"
  565. # 305 "kind.ag"
  566. rsyncCmd += "--exclude-from=" + imageFullName + "/exclude ";
  567. # 306 "kind.ag"
  568. if (!referenceImage.empty())
  569. # 307 "kind.ag"
  570. rsyncCmd += "--link-dest=" + referenceImage + "/tree ";
  571. # 308 "kind.ag"
  572. rsyncCmd += userAtHost + ":" + path + " ";
  573. # 309 "kind.ag"
  574. rsyncCmd += imageFullName + "/tree";
  575. # 310 "kind.ag"
  576. } // shell mode
  577. # 311 "kind.ag"
  578. else
  579. # 312 "kind.ag"
  580. {
  581. # 313 "kind.ag"
  582. // cout << "USING SERVERMODE" << endl;
  583. # 314 "kind.ag"
  584. vector<string> excluded;
  585. # 315 "kind.ag"
  586. if (conf.hasKey("exclude"))
  587. # 316 "kind.ag"
  588. {
  589. # 317 "kind.ag"
  590. Strings excludes = conf.getStrings("exclude");
  591. # 318 "kind.ag"
  592. for (string s : excludes)
  593. # 319 "kind.ag"
  594. excluded.push_back(s);
  595. # 320 "kind.ag"
  596. }
  597. # 321 "kind.ag"
  598. # 322 "kind.ag"
  599. if (!dryRun)
  600. # 323 "kind.ag"
  601. strings2File(excluded, imageFullName + "/exclude");
  602. # 324 "kind.ag"
  603. # 325 "kind.ag"
  604. rsyncCmd += "--exclude-from=" + imageFullName + "/exclude ";
  605. # 326 "kind.ag"
  606. if (!referenceImage.empty())
  607. # 327 "kind.ag"
  608. rsyncCmd += "--link-dest=" + referenceImage + "/tree ";
  609. # 328 "kind.ag"
  610. rsyncCmd += conf.getString("server") + "::" + path + " ";
  611. # 329 "kind.ag"
  612. rsyncCmd += imageFullName + "/tree";
  613. # 330 "kind.ag"
  614. }
  615. # 331 "kind.ag"
  616. # 332 "kind.ag"
  617. debugPrint("Action: " + rsyncCmd);
  618. # 333 "kind.ag"
  619. # 334 "kind.ag"
  620. vector<string> backupResult;
  621. # 335 "kind.ag"
  622. if (!dryRun)
  623. # 336 "kind.ag"
  624. {
  625. # 337 "kind.ag"
  626. verbosePrint("syncing (" + rsyncCmd + ")");
  627. # 338 "kind.ag"
  628. int rc;
  629. # 339 "kind.ag"
  630. backupResult = myPopen(rsyncCmd, rc, debug, imageFullName + "/rsync-log");
  631. # 340 "kind.ag"
  632. // strings2File(backupResult, imageFullName + "/rsync-log");
  633. # 341 "kind.ag"
  634. if (rc == 0 ||
  635. # 342 "kind.ag"
  636. rc == 24 || // "no error" or "vanished source files" (ignored)
  637. # 343 "kind.ag"
  638. rc == 6114) // workaround for wrong exit code ??!!
  639. # 344 "kind.ag"
  640. {
  641. # 345 "kind.ag"
  642. unlink(errorfile.c_str());
  643. # 346 "kind.ag"
  644. string lastLink = vaultpath + "/last";
  645. # 347 "kind.ag"
  646. unlink(lastLink.c_str());
  647. # 348 "kind.ag"
  648. symlink(imageFullName.c_str(), lastLink.c_str());
  649. # 349 "kind.ag"
  650. long int st = 0;
  651. # 350 "kind.ag"
  652. long int sc = 0;
  653. # 351 "kind.ag"
  654. for (auto bl : backupResult)
  655. # 352 "kind.ag"
  656. {
  657. # 353 "kind.ag"
  658. if (bl.substr(0, 15) == "Total file size")
  659. # 354 "kind.ag"
  660. st = getNumber(bl);
  661. # 355 "kind.ag"
  662. else if (bl.substr(0, 27) == "Total transferred file size")
  663. # 356 "kind.ag"
  664. sc = getNumber(bl);
  665. # 357 "kind.ag"
  666. }
  667. # 358 "kind.ag"
  668. // sizes[vault] = pair<long int, long int>(st, sc);
  669. # 359 "kind.ag"
  670. sizes[vault] = Sizes(st, sc);
  671. # 360 "kind.ag"
  672. // cout << vault << " " << st << " || " << sc << endl;
  673. # 361 "kind.ag"
  674. }
  675. # 362 "kind.ag"
  676. else
  677. # 363 "kind.ag"
  678. throw Exception("Backup", "Failed to execute rsync (result: " + to_string(rc) + ")");
  679. # 364 "kind.ag"
  680. }
  681. # 365 "kind.ag"
  682. else
  683. # 366 "kind.ag"
  684. cout << "Not executing " << rsyncCmd << endl;
  685. # 367 "kind.ag"
  686. # 368 "kind.ag"
  687. string rule;
  688. # 369 "kind.ag"
  689. createExpireFile(imageFullName, conf, rule);
  690. # 370 "kind.ag"
  691. }
  692. # 371 "kind.ag"
  693. catch (Exception ex)
  694. # 372 "kind.ag"
  695. {
  696. # 373 "kind.ag"
  697. cerr << "Exception in vault " << vault << ": " << ex.what() << endl;
  698. # 374 "kind.ag"
  699. }
  700. # 375 "kind.ag"
  701. }
  702. # 376 "kind.ag"
  703. # 377 "kind.ag"
  704. int removeDir(const string& path)
  705. # 378 "kind.ag"
  706. {
  707. # 379 "kind.ag"
  708. debugPrint("removeDir " + path);
  709. # 380 "kind.ag"
  710. DIR* d = opendir(path.c_str());
  711. # 381 "kind.ag"
  712. # 382 "kind.ag"
  713. int r = -1;
  714. # 383 "kind.ag"
  715. if (d)
  716. # 384 "kind.ag"
  717. {
  718. # 385 "kind.ag"
  719. struct dirent* p;
  720. # 386 "kind.ag"
  721. # 387 "kind.ag"
  722. r = 0;
  723. # 388 "kind.ag"
  724. while (!r && (p = readdir(d)))
  725. # 389 "kind.ag"
  726. {
  727. # 390 "kind.ag"
  728. int r2 = 0;
  729. # 391 "kind.ag"
  730. string fn = p->d_name;
  731. # 392 "kind.ag"
  732. if (fn != "." && fn != "..")
  733. # 393 "kind.ag"
  734. {
  735. # 394 "kind.ag"
  736. fn = path + "/" + fn;
  737. # 395 "kind.ag"
  738. debugPrint("-- " + fn);
  739. # 396 "kind.ag"
  740. struct stat statbuf;
  741. # 397 "kind.ag"
  742. if (lstat(fn.c_str(), &statbuf) == 0)
  743. # 398 "kind.ag"
  744. {
  745. # 399 "kind.ag"
  746. if (S_ISLNK(statbuf.st_mode))
  747. # 400 "kind.ag"
  748. {
  749. # 401 "kind.ag"
  750. debugPrint("Remove link " + fn);
  751. # 402 "kind.ag"
  752. r2 = unlink(fn.c_str());
  753. # 403 "kind.ag"
  754. }
  755. # 404 "kind.ag"
  756. else if (S_ISDIR(statbuf.st_mode))
  757. # 405 "kind.ag"
  758. {
  759. # 406 "kind.ag"
  760. debugPrint("Remove dir " + fn);
  761. # 407 "kind.ag"
  762. r2 = removeDir(fn);
  763. # 408 "kind.ag"
  764. }
  765. # 409 "kind.ag"
  766. else
  767. # 410 "kind.ag"
  768. {
  769. # 411 "kind.ag"
  770. debugPrint("Remove file " + fn);
  771. # 412 "kind.ag"
  772. r2 = unlink(fn.c_str());
  773. # 413 "kind.ag"
  774. }
  775. # 414 "kind.ag"
  776. }
  777. # 415 "kind.ag"
  778. else
  779. # 416 "kind.ag"
  780. {
  781. # 417 "kind.ag"
  782. cout << "stat(" << fn << ") failed" << endl;
  783. # 418 "kind.ag"
  784. // we assume "file" here
  785. # 419 "kind.ag"
  786. r2 = unlink(fn.c_str());
  787. # 420 "kind.ag"
  788. }
  789. # 421 "kind.ag"
  790. }
  791. # 422 "kind.ag"
  792. r = r2;
  793. # 423 "kind.ag"
  794. }
  795. # 424 "kind.ag"
  796. closedir(d);
  797. # 425 "kind.ag"
  798. }
  799. # 426 "kind.ag"
  800. # 427 "kind.ag"
  801. if (r == 0)
  802. # 428 "kind.ag"
  803. {
  804. # 429 "kind.ag"
  805. debugPrint("Remove Dir itself " + path);
  806. # 430 "kind.ag"
  807. r = rmdir(path.c_str());
  808. # 431 "kind.ag"
  809. }
  810. # 432 "kind.ag"
  811. # 433 "kind.ag"
  812. return r;
  813. # 434 "kind.ag"
  814. }
  815. # 435 "kind.ag"
  816. # 436 "kind.ag"
  817. #if 0
  818. # 437 "kind.ag"
  819. int removeDir(const string& dname)
  820. # 438 "kind.ag"
  821. {
  822. # 439 "kind.ag"
  823. int rc = 0;
  824. # 440 "kind.ag"
  825. if (!dryRun)
  826. # 441 "kind.ag"
  827. {
  828. # 442 "kind.ag"
  829. Strings files;
  830. # 443 "kind.ag"
  831. // subdirectories
  832. # 444 "kind.ag"
  833. dirList(dname, files);
  834. # 445 "kind.ag"
  835. for (unsigned int i = 0; i < files.size(); ++i)
  836. # 446 "kind.ag"
  837. {
  838. # 447 "kind.ag"
  839. debugPrint("Remove dir " + files[i]);
  840. # 448 "kind.ag"
  841. for (unsigned int i = 0; i < files.size(); ++i)
  842. # 449 "kind.ag"
  843. rc += removeDir(files[i]);
  844. # 450 "kind.ag"
  845. }
  846. # 451 "kind.ag"
  847. files.clear();
  848. # 452 "kind.ag"
  849. # 453 "kind.ag"
  850. // files in directory
  851. # 454 "kind.ag"
  852. fileList(dname, files);
  853. # 455 "kind.ag"
  854. for (unsigned int i = 0; i < files.size(); ++i)
  855. # 456 "kind.ag"
  856. {
  857. # 457 "kind.ag"
  858. debugPrint("unlink " + files[i]);
  859. # 458 "kind.ag"
  860. if (!dryRun)
  861. # 459 "kind.ag"
  862. {
  863. # 460 "kind.ag"
  864. if (unlink(files[i].c_str()) != 0)
  865. # 461 "kind.ag"
  866. rc++;
  867. # 462 "kind.ag"
  868. }
  869. # 463 "kind.ag"
  870. }
  871. # 464 "kind.ag"
  872. debugPrint("rmdir " + dname);
  873. # 465 "kind.ag"
  874. # 466 "kind.ag"
  875. // directory
  876. # 467 "kind.ag"
  877. if (rmdir(dname.c_str()) != 0)
  878. # 468 "kind.ag"
  879. rc++;
  880. # 469 "kind.ag"
  881. }
  882. # 470 "kind.ag"
  883. # 471 "kind.ag"
  884. return rc;
  885. # 472 "kind.ag"
  886. }
  887. # 473 "kind.ag"
  888. #endif
  889. # 474 "kind.ag"
  890. # 475 "kind.ag"
  891. void expireVault(const string& vault, KindConfig conf, DateTime now)
  892. # 476 "kind.ag"
  893. {
  894. # 477 "kind.ag"
  895. if (!quiet)
  896. # 478 "kind.ag"
  897. cout << DateTime::now().getString('h') << ": Expiring images in vault " << vault << endl;
  898. # 479 "kind.ag"
  899. # 480 "kind.ag"
  900. readVaultConfig(vault, conf);
  901. # 481 "kind.ag"
  902. # 482 "kind.ag"
  903. string vaultpath = findVault(vault);
  904. # 483 "kind.ag"
  905. # 484 "kind.ag"
  906. Strings dirlist; // list of subdirectories
  907. # 485 "kind.ag"
  908. dirList(vaultpath, dirlist);
  909. # 486 "kind.ag"
  910. # 487 "kind.ag"
  911. Strings validImages;
  912. # 488 "kind.ag"
  913. Strings invalidImages;
  914. # 489 "kind.ag"
  915. string imgname = getImageName(conf);
  916. # 490 "kind.ag"
  917. # 491 "kind.ag"
  918. for (unsigned int i = 0; i < dirlist.size(); ++i)
  919. # 492 "kind.ag"
  920. {
  921. # 493 "kind.ag"
  922. FileName fn(dirlist[i]);
  923. # 494 "kind.ag"
  924. if (startsWith(fn.getName(), imgname)) // dir is image ?
  925. # 495 "kind.ag"
  926. {
  927. # 496 "kind.ag"
  928. debugPrint(dirlist[i]);
  929. # 497 "kind.ag"
  930. # 498 "kind.ag"
  931. DateTime t = imageDate(dirlist[i]);
  932. # 499 "kind.ag"
  933. # 500 "kind.ag"
  934. if (t != now) // ignore just created image
  935. # 501 "kind.ag"
  936. {
  937. # 502 "kind.ag"
  938. if (!isValidImage(dirlist[i])) // invalid image?
  939. # 503 "kind.ag"
  940. {
  941. # 504 "kind.ag"
  942. invalidImages.push_back(dirlist[i]);
  943. # 505 "kind.ag"
  944. debugPrint("- invalid image");
  945. # 506 "kind.ag"
  946. }
  947. # 507 "kind.ag"
  948. else
  949. # 508 "kind.ag"
  950. {
  951. # 509 "kind.ag"
  952. validImages.push_back(dirlist[i]);
  953. # 510 "kind.ag"
  954. debugPrint("- valid image");
  955. # 511 "kind.ag"
  956. }
  957. # 512 "kind.ag"
  958. }
  959. # 513 "kind.ag"
  960. else
  961. # 514 "kind.ag"
  962. debugPrint("- current image - ignored");
  963. # 515 "kind.ag"
  964. }
  965. # 516 "kind.ag"
  966. }
  967. # 517 "kind.ag"
  968. # 518 "kind.ag"
  969. for (unsigned int i = 0; i < invalidImages.size(); ++i)
  970. # 519 "kind.ag"
  971. {
  972. # 520 "kind.ag"
  973. try
  974. # 521 "kind.ag"
  975. {
  976. # 522 "kind.ag"
  977. DateTime t = imageDate(invalidImages[i]);
  978. # 523 "kind.ag"
  979. DateTime expireTime = t + stot(conf.getString("expireFailedImage"));
  980. # 524 "kind.ag"
  981. if (debug)
  982. # 525 "kind.ag"
  983. {
  984. # 526 "kind.ag"
  985. cout << "image: " << t.getString('h') << " expire: " << expireTime.getString('h') << endl;
  986. # 527 "kind.ag"
  987. cout << " now: " << now.getString('h') << endl;
  988. # 528 "kind.ag"
  989. }
  990. # 529 "kind.ag"
  991. if (expireTime < now)
  992. # 530 "kind.ag"
  993. {
  994. # 531 "kind.ag"
  995. if (!quiet)
  996. # 532 "kind.ag"
  997. cout << " removing invalid image " << invalidImages[i] << endl;
  998. # 533 "kind.ag"
  999. if (removeDir(invalidImages[i]) != 0)
  1000. # 534 "kind.ag"
  1001. cout << "Error removing " << invalidImages[i] << endl;
  1002. # 535 "kind.ag"
  1003. }
  1004. # 536 "kind.ag"
  1005. }
  1006. # 537 "kind.ag"
  1007. catch (Exception ex)
  1008. # 538 "kind.ag"
  1009. {
  1010. # 539 "kind.ag"
  1011. cerr << "Exception: " << ex.what() << endl;
  1012. # 540 "kind.ag"
  1013. }
  1014. # 541 "kind.ag"
  1015. }
  1016. # 542 "kind.ag"
  1017. # 543 "kind.ag"
  1018. sort(validImages.begin(), validImages.end()); // lexicographical order == temporal order
  1019. # 544 "kind.ag"
  1020. for (unsigned int i = 0;
  1021. # 545 "kind.ag"
  1022. i < validImages.size() - 1; // never expire latest image
  1023. # 546 "kind.ag"
  1024. ++i)
  1025. # 547 "kind.ag"
  1026. {
  1027. # 548 "kind.ag"
  1028. try
  1029. # 549 "kind.ag"
  1030. {
  1031. # 550 "kind.ag"
  1032. string imageName = validImages[i];
  1033. # 551 "kind.ag"
  1034. DateTime imageTime = imageDate(imageName);
  1035. # 552 "kind.ag"
  1036. string rule;
  1037. # 553 "kind.ag"
  1038. DateTime expireTime = expireDate(imageName, conf, rule);
  1039. # 554 "kind.ag"
  1040. # 555 "kind.ag"
  1041. if (debug)
  1042. # 556 "kind.ag"
  1043. {
  1044. # 557 "kind.ag"
  1045. cout << "image: " << imageTime.getString('h') << " expire: " << expireTime.getString('h') << endl;
  1046. # 558 "kind.ag"
  1047. cout << " now: " << now.getString('h') << endl;
  1048. # 559 "kind.ag"
  1049. }
  1050. # 560 "kind.ag"
  1051. if (now > expireTime)
  1052. # 561 "kind.ag"
  1053. {
  1054. # 562 "kind.ag"
  1055. if (!quiet)
  1056. # 563 "kind.ag"
  1057. cout << "removing " << imageName << " rule=" << rule << endl;
  1058. # 564 "kind.ag"
  1059. removeDir(imageName);
  1060. # 565 "kind.ag"
  1061. }
  1062. # 566 "kind.ag"
  1063. }
  1064. # 567 "kind.ag"
  1065. catch (Exception ex)
  1066. # 568 "kind.ag"
  1067. {
  1068. # 569 "kind.ag"
  1069. cerr << "Exception: " << ex.what() << endl;
  1070. # 570 "kind.ag"
  1071. }
  1072. # 571 "kind.ag"
  1073. }
  1074. # 572 "kind.ag"
  1075. }
  1076. # 573 "kind.ag"
  1077. # 574 "kind.ag"
  1078. /*AppGen:Main*/
  1079. string ag_programName;
  1080. void usage()
  1081. {
  1082. cout << ag_programName << " - archiving backup" << endl;
  1083. cout << "Aufruf:" << endl;
  1084. cout << ag_programName << " [<options>] vault_or_group " << endl;
  1085. cout << " vault_or_group - Vault to backup" << endl;
  1086. cout << "Optionen:" << endl;
  1087. cout << " -f --full Force full image == initial backup (default: false)" << endl;
  1088. cout << " -c --masterconfig Master config file (default: \"\")" << endl;
  1089. cout << " if not given or empty kind looks for" << endl;
  1090. cout << " /etc/kind/master.conf" << endl;
  1091. cout << " /ffp/etc/kind/master.conf" << endl;
  1092. cout << " -B --backuponly Only backup/no expire (default: false)" << endl;
  1093. cout << " -E --expireonly Only expire/no backup (default: false)" << endl;
  1094. cout << " -D --dryrun Dry run (no real backup) (default: false)" << endl;
  1095. cout << " -C --listconfig Show configuration (default: false)" << endl;
  1096. cout << " -v --verbose Verbose (default: false)" << endl;
  1097. cout << " -d --debug Debug output of many data (default: false)" << endl;
  1098. cout << " -q --quiet Be quiet - no messages (default: false)" << endl;
  1099. cout << " -h --help This help" << endl;
  1100. exit(1);
  1101. }
  1102. void error(const string& msg)
  1103. {
  1104. cout << endl << ag_programName << " - error: " << msg << endl << endl;
  1105. usage();
  1106. }
  1107. int ptoi(const char* para)
  1108. {
  1109. char* end;
  1110. int res = strtol(para, &end, 10);
  1111. if (end == para)
  1112. error(string("no int: ") + para);
  1113. if (*end != 0)
  1114. error(string("garbage in int: ") + para);
  1115. return res;
  1116. }
  1117. double ptod(const char* para)
  1118. {
  1119. char* end;
  1120. double res = strtod(para, &end);
  1121. if (end == para)
  1122. error(string("no double: ") + para);
  1123. if (*end != 0)
  1124. error(string("garbage in double: ") + para);
  1125. return res;
  1126. }
  1127. int main(int argc, char** argv)
  1128. {
  1129. bool fullImage = false;
  1130. string masterConfig = "";
  1131. bool backupOnly = false;
  1132. bool expireOnly = false;
  1133. bool listConfig = false;
  1134. string vault = "";
  1135. static struct option ag_long_options[] =
  1136. {
  1137. {"full", no_argument, 0, 'f' },
  1138. {"masterconfig", required_argument, 0, 'c' },
  1139. {"backuponly", no_argument, 0, 'B' },
  1140. {"expireonly", no_argument, 0, 'E' },
  1141. {"dryrun", no_argument, 0, 'D' },
  1142. {"listconfig", no_argument, 0, 'C' },
  1143. {"verbose", no_argument, 0, 'v' },
  1144. {"debug", no_argument, 0, 'd' },
  1145. {"quiet", no_argument, 0, 'q' },
  1146. {"help", no_argument, 0, 'h' },
  1147. {0, 0, 0, 0 }
  1148. };
  1149. ag_programName = argv[0];
  1150. int rc;
  1151. opterr = 0;
  1152. while ((rc = getopt_long(argc, argv, ":fc:BEDCvdqh", ag_long_options, NULL)) >= 0)
  1153. {
  1154. switch (rc)
  1155. {
  1156. case '?':
  1157. error("Unknown option");
  1158. break;
  1159. case ':':
  1160. error("Expecting option parameter");
  1161. break;
  1162. case 'f':
  1163. fullImage = true;
  1164. break;
  1165. case 'c':
  1166. masterConfig = optarg;
  1167. break;
  1168. case 'B':
  1169. backupOnly = true;
  1170. break;
  1171. case 'E':
  1172. expireOnly = true;
  1173. break;
  1174. case 'D':
  1175. dryRun = true;
  1176. break;
  1177. case 'C':
  1178. listConfig = true;
  1179. break;
  1180. case 'v':
  1181. verbose = true;
  1182. break;
  1183. case 'd':
  1184. debug = true;
  1185. break;
  1186. case 'q':
  1187. quiet = true;
  1188. break;
  1189. case 'h':
  1190. usage();
  1191. break;
  1192. default:
  1193. error("error in options");
  1194. }
  1195. }
  1196. if (optind < argc)
  1197. vault = argv[optind++];
  1198. else error("Parameter vault_or_group needed");
  1199. /*AppGen:MainEnd*/
  1200. # 578 "kind.ag"
  1201. # 579 "kind.ag"
  1202. int exitCode = 0;
  1203. # 580 "kind.ag"
  1204. string lockFile;
  1205. # 581 "kind.ag"
  1206. try
  1207. # 582 "kind.ag"
  1208. {
  1209. # 583 "kind.ag"
  1210. if (debug)
  1211. # 584 "kind.ag"
  1212. verbose = true;
  1213. # 585 "kind.ag"
  1214. # 586 "kind.ag"
  1215. KindConfig conf;
  1216. # 587 "kind.ag"
  1217. # 588 "kind.ag"
  1218. // default-values
  1219. # 589 "kind.ag"
  1220. conf.add("imageName", "image");
  1221. # 590 "kind.ag"
  1222. conf.add("vaultConfigName", "kind/vault.conf");
  1223. # 591 "kind.ag"
  1224. conf.add("expireFailedImage", "3 days");
  1225. # 592 "kind.ag"
  1226. conf.add("expireRule", "* * * * 1 month");
  1227. # 593 "kind.ag"
  1228. conf.add("rsyncOption", ""); // no additional rsync option
  1229. # 594 "kind.ag"
  1230. conf.add("remoteShell", "");
  1231. # 595 "kind.ag"
  1232. conf.add("lockfile", "/var/lock/kind");
  1233. # 596 "kind.ag"
  1234. conf.add("userExcludeFile", "nobackup.list");
  1235. # 597 "kind.ag"
  1236. conf.add("userExcludeCommand",
  1237. # 598 "kind.ag"
  1238. "find %path -type f -iname '*nobackup' -printf '%P\\\\n'");
  1239. # 599 "kind.ag"
  1240. conf.add("logSize", "");
  1241. # 600 "kind.ag"
  1242. # 601 "kind.ag"
  1243. if (listConfig)
  1244. # 602 "kind.ag"
  1245. {
  1246. # 603 "kind.ag"
  1247. cout << "builtin config" << endl;
  1248. # 604 "kind.ag"
  1249. conf.print(". ");
  1250. # 605 "kind.ag"
  1251. }
  1252. # 606 "kind.ag"
  1253. # 607 "kind.ag"
  1254. readMasterConfig(masterConfig, conf);
  1255. # 608 "kind.ag"
  1256. # 609 "kind.ag"
  1257. banks = conf.getStrings("bank");
  1258. # 610 "kind.ag"
  1259. if (banks.empty())
  1260. # 611 "kind.ag"
  1261. throw Exception("read master config", "no banks defined");
  1262. # 612 "kind.ag"
  1263. # 613 "kind.ag"
  1264. if (listConfig)
  1265. # 614 "kind.ag"
  1266. {
  1267. # 615 "kind.ag"
  1268. cout << "global config:" << endl;
  1269. # 616 "kind.ag"
  1270. conf.print(". ");
  1271. # 617 "kind.ag"
  1272. readVaultConfig(vault, conf);
  1273. # 618 "kind.ag"
  1274. cout << "vault config:" << endl;
  1275. # 619 "kind.ag"
  1276. conf.print(". ");
  1277. # 620 "kind.ag"
  1278. exit(0);
  1279. # 621 "kind.ag"
  1280. }
  1281. # 622 "kind.ag"
  1282. # 623 "kind.ag"
  1283. lockFile = conf.getString("lockfile");
  1284. # 624 "kind.ag"
  1285. createLock(lockFile);
  1286. # 625 "kind.ag"
  1287. # 626 "kind.ag"
  1288. DateTime imageTime = DateTime::now();
  1289. # 627 "kind.ag"
  1290. string logSizeFile = conf.getString("logSize");
  1291. # 628 "kind.ag"
  1292. if (!logSizeFile.empty() && fileExists(logSizeFile))
  1293. # 629 "kind.ag"
  1294. {
  1295. # 630 "kind.ag"
  1296. vector<string> ss;
  1297. # 631 "kind.ag"
  1298. file2Strings(logSizeFile, ss);
  1299. # 632 "kind.ag"
  1300. for (auto s : ss)
  1301. # 633 "kind.ag"
  1302. {
  1303. # 634 "kind.ag"
  1304. unsigned int i = 0;
  1305. # 635 "kind.ag"
  1306. string v = getWord(s, i);
  1307. # 636 "kind.ag"
  1308. long int s1 = getLongInt(s, i);
  1309. # 637 "kind.ag"
  1310. long int s2 = getLongInt(s, i);
  1311. # 638 "kind.ag"
  1312. sizes[v] = Sizes(s1, s2);
  1313. # 639 "kind.ag"
  1314. }
  1315. # 640 "kind.ag"
  1316. }
  1317. # 641 "kind.ag"
  1318. # 642 "kind.ag"
  1319. vector<string> vaults;
  1320. # 643 "kind.ag"
  1321. string groupname = "group_" + vault;
  1322. # 644 "kind.ag"
  1323. if (conf.hasKey(groupname))
  1324. # 645 "kind.ag"
  1325. vaults = conf.getStrings(groupname);
  1326. # 646 "kind.ag"
  1327. else
  1328. # 647 "kind.ag"
  1329. vaults.push_back(vault);
  1330. # 648 "kind.ag"
  1331. # 649 "kind.ag"
  1332. if (!expireOnly)
  1333. # 650 "kind.ag"
  1334. for (unsigned int i = 0; i < vaults.size(); ++i)
  1335. # 651 "kind.ag"
  1336. {
  1337. # 652 "kind.ag"
  1338. backupVault(vaults[i], conf, imageTime, fullImage);
  1339. # 653 "kind.ag"
  1340. if (!logSizeFile.empty())
  1341. # 654 "kind.ag"
  1342. {
  1343. # 655 "kind.ag"
  1344. Strings st;
  1345. # 656 "kind.ag"
  1346. for (auto s : sizes)
  1347. # 657 "kind.ag"
  1348. {
  1349. # 658 "kind.ag"
  1350. string h = s.first + " " + to_string(s.second.first) + " " + to_string(s.second.second);
  1351. # 659 "kind.ag"
  1352. st.push_back(h);
  1353. # 660 "kind.ag"
  1354. }
  1355. # 661 "kind.ag"
  1356. strings2File(st, logSizeFile);
  1357. # 662 "kind.ag"
  1358. }
  1359. # 663 "kind.ag"
  1360. }
  1361. # 664 "kind.ag"
  1362. # 665 "kind.ag"
  1363. if (!backupOnly)
  1364. # 666 "kind.ag"
  1365. for (unsigned int i = 0; i < vaults.size(); ++i)
  1366. # 667 "kind.ag"
  1367. expireVault(vaults[i], conf, imageTime);
  1368. # 668 "kind.ag"
  1369. # 669 "kind.ag"
  1370. if (!quiet)
  1371. # 670 "kind.ag"
  1372. cout << DateTime::now().getString('h') << ": finished" << endl;
  1373. # 671 "kind.ag"
  1374. # 672 "kind.ag"
  1375. }
  1376. # 673 "kind.ag"
  1377. catch (const Exception& ex)
  1378. # 674 "kind.ag"
  1379. {
  1380. # 675 "kind.ag"
  1381. cerr << "Exception: " << ex.what() << endl;
  1382. # 676 "kind.ag"
  1383. exitCode = 1;
  1384. # 677 "kind.ag"
  1385. }
  1386. # 678 "kind.ag"
  1387. catch (const char* msg)
  1388. # 679 "kind.ag"
  1389. {
  1390. # 680 "kind.ag"
  1391. cerr << "Exception(char*): " << msg << endl;
  1392. # 681 "kind.ag"
  1393. exitCode = 1;
  1394. # 682 "kind.ag"
  1395. }
  1396. # 683 "kind.ag"
  1397. catch (const string& msg)
  1398. # 684 "kind.ag"
  1399. {
  1400. # 685 "kind.ag"
  1401. cerr << "Exception(string): " << msg << endl;
  1402. # 686 "kind.ag"
  1403. exitCode = 1;
  1404. # 687 "kind.ag"
  1405. }
  1406. # 688 "kind.ag"
  1407. removeLock(lockFile);
  1408. # 689 "kind.ag"
  1409. return exitCode;
  1410. # 690 "kind.ag"
  1411. }