kind.cpp 38 KB

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