kind.cpp 37 KB

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