1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link href="style.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<title>Libdar API - Tutorial</title>
</head>
<body>
<div class=top>
<img alt="Dar Documentation" src="dar_s_doc.jpg" style="float:left;">
<div class=h1>
<h1>Libdar APplication Interface (API) tutorial</h1>
(API version 6.x.x)
</div>
</div>
<h2>Presentation</h2>
<p>
The Libdar library provides a
complete abstraction layer for handling
<i>Dar</i> archives. The general
operations provided are:
</p>
<ul>
<li>archive creation,</li>
<li>file extraction from archive,</li>
<li>archive listing,</li>
<li>archive testing,</li>
<li>archive comparison,</li>
<li>catalogue isolation,</li>
<li>archive merging,</li>
<li>archive reparation</li>
<li>dar_manager database manipulations</li>
<li>dar_slave steering</li>
<li>dar_xform operation</li>
</ul>
<p>
Note that <i>Disk ARchive</i> <b>and</b>
<i>libdar</i>
have been released under the <b>Gnu
General Public License (GPL)</b>.
All code linked to libdar
(statically or dynamically), <b>must</b>
also be covered by the GPL or compatible license.
Commercial use is prohibited unless otherwise
explicitely agreeded with libdar's author.
</p>
<p>
This tutorial will show you how to
use the libdar API. Since release 2.0.0 the
<i>dar</i> command-line executable also
relies on this API, looking at it's code may provide a good
illustration on the way to use libdar,
the file <code>src/dar_suite/dar.cpp</code>
is the primary consumer of the libdar API.
However we will see here, step by step how
you can leverage the API for your own use.
</p>
<p>
In the following sample codes will be provided, they
are solely illustrative and is not guaranteed to compile.
Reference documentation for this API
is contained in the source code as doxygen comment which
can be extracted and "compiled" in the
the <code>doc/html</code> directory when compiling dar/libdar.
This API reference document is also available
<a href="http://dar.linux.free.fr/doc/html/index.html">online</a>
and will be referred below as the <i>API reference documentation</i>.
</p>
<h2>Let's Start</h2>
<h3>Conventions</h3>
<h4>Language</h4>
<p>
Dar and libdar are written in
C++, and so is the libdar fundamental API. Though you can find
a <b>Python</b> binding in the <code>src/python</code> subdirectory,
which strongly follows the class hierarchy that will see here with
C++ sample code. The <a href="python/libdar_test.py">libdar_test.py</a>
document rawly follows with <i>python</i> code what we will see
below with C++.
</p>
<p>
Feel free to contribute if you want bindings for other languages.
</p>
<h4>Header files</h4>
<p>
Only one include file is required in your program to have access to
libdar:
</p>
<code class=block>
#include <dar/libdar.hpp>
</code>
<h4>Libdar namespace</h4>
<p>
All libdar symbols are defined within
the <b>libdar namespace</b>. You
can either add the <code>using namespace libdar;</code>
statement at the beginning of your source files...
</p>
<code class=block>
using namespace libdar;
get_version();
...
</code>
<p>
...or, as shown below, you can
explicitly use the namespace in front of libdar symbols,
we will use this notation in the following, which has the
advantage of avoiding name conflicts and clarify origin of the
symbols used, but lead to a more heavier code, less easy to
read:
</p>
<code class=block>
libdar::get_version();
...
</code>
<h4>Exceptions</h4>
<p>
The library makes use of
exception to report unexpected conditions. These contain the reason and
context the error occurred in, so you can be catch these in your code
to display details of the error and its cause. All exceptions used within
libdar inherit from the pure virtual class <b>libdar::Egeneric</b>
</p>
<p>
Most of the time you will use only one of the following two methods:
</p>
<ul>
<li><code>std::string & get_message() const</code></li>
<li><code>std::string & dump_str() const</code></li>
</ul>
<dl>
<dt class=void>get_message()</dt><dd>
returns a message string describing the error met
</dd>
<dt class=void>dump_str()</dt><dd>
returns a text paragraph with additional information about
the stack as well as context the error occurred in.
</dd>
</dl>
<p>
Now, messages are for human, you may need to provide different
behaviors depending on the type of the error libdar has met and
which triggers such exception. This is can be done by checking the
type of the exception.
</p>
<p>
We will only focus on most common exception type read the
<i>API reference documentation</i> for an exhaustive list of the exception
type used by libdar:
</p>
<dl>
<dt class=void>libdar::Ebug</dt><dd>
This one is used when <i>a-situation-that-should-never-occur</i>
is met and can be assumed to be a bug in libdar. Using the
<code>get_message()</code> method in that
situation would not provide all necessary details to understand
and fix the bug, so it is advised to always use <code>dump_str()</code>
for that specific type of exception and abort further execution regarding
libdar.
</dd>
<dt class=void>libdar::Erange</dt><dd>
A parameter or a value is out of range, details is provided
with <code>get_message()</code>
</dd>
<dt class=void>libdar::Ememory</dt><dd>
Libdar lacked of virtual memory to proceed to the requested operation
</dd>
<dt class=void>libdar::Einfinint</dt><dd>
an arythmetic error occurred when using <code>libdar::infinint</code>
object, which is a internal integer type that can handle arbitrary
large numbers. Today it is only used if libdar has been compiled
with <code>--enable-mode=infinint</code> so you are not likely to meet
it.
</dd>
<dt class=void>libdar::Elimitint</dt><dd>
when <i>infinint</i> are not used, a wrapper class over system
integers is used to detect integer overflow. In that situation,
this exception is thrown, enjoying the user to use a <i>infinint</i>
based flavor of libdar to avoid this error
</dd>
<dt class=void>libdar::Ehardware</dt><dd>
used when the operating system returned an I/O error or hardware
related error
</dd>
<dt class=void>libdar::Esystem</dt><dd>
When software related error is reported by the system, like lack of
ownership, permission or non existing file...
</dd>
<dt class=void>libdar::Euser_abort</dt><dd>
This exception is thrown as the consequence of user request to
abort the process. This may occur when aswnering to a question
issued by libdar.
</dd>
<dt class=void>libda::Ethread_cancel</dt><dd>
used when a program has called the thread cancellation routine
of libdar, which drives libdar to stop as soon as possible (immediately
when the control point is met, or delayed aborting cleanly the operation
under process depending on the option used to cancel the running libdar
thread.
</dd>
</dl>
<p>
Some other exist and are well described in the
<i>API reference documentation</i>. You can thus wrap the whole
libdar interaction with a statement like in the following example:
</p>
<code class=block>
try
{
// calls to libdar
...
//
}
catch(libdar::Ebug & e)
{
std::string msg = e.dump_str();
// do something with msg like for example:
std::cerr << msg << std::endl;
}
catch(libdar::Euser_abort & e)
{
// some specific treatment for this
// type of exception
...
}
catch(libdar::Egeneric & e)
{
// a global treatment for all other libdar exceptions
std::string msg = e.get_message(); << std::endl;
...
}
</code>
<h2>First we must initialize libdar</h2>
<p>
the libdar initialization is
performed by calling the <code>libdar::get_version()</code>
function.
</p>
<p>
This function can be called several time though only once is necessary,
but this call has to complete before any other call to libdar.
</p>
<p>
In a <b>multi-thread context</b> libthreadar
initialization is not re-entrant. In other word the first
call to <code>libdar::get_version()</code> must complete
before any other call to libdar can take place in another
thread of the running process. Once libdar has
been initialized, you can call <code>libdar::get_version()</code>
concurrently from several threads at the same time without
problem.
</p>
<code class=block>
libdar::get_version();
</code>
<h2>We should prepare the end right now</h2>
<p>
Libdar used some
data-structures (mutex, secured memory, etc.) that need to be released
properly before ending the process. It is important to invoke the
<code>close_and_clean()</code> function before exiting your program if you
had called <code>get_version()</code> previously. After that,
the only allowed call to libdar is <code>get_version()</code>.
</p>
<code class=block>
libdar::close_and_clean()
</code>
<dl>
<dt class=void>Note:</dt><dd>
<code>closes_and_clean()</code>
makes the necessary for memory to be released in the
proper order.
<u>
Not calling close_and_clean() at the
end of your program may result in
uncaught exception message from libdar at the end of
the execution.
</u>
This depends on the compiler, libc and option
activated in libdar at compilation time.
</dd>
</dl>
<p>
All in one, at the highest level, you code should look like the following:
</p>
<code class=block>
libdar::get_version();
try
{
try
{
// calls to libdar
// thing we will see in next
...
...
}
catch(libdar::Ebug & e)
{
std::string msg = e.dump_str();
// do something with msg like for example:
std::cerr << msg << std::endl;
}
catch(libdar::Egeneric & e)
{
std::string msg = e.get_message();
// do something with msg like for example
std::cerr << msg << std::endl;
}
}
catch(...)
{
libdar::close_and_clean();
throw;
}
libdar::close_and_clean();
</code>
<h2>Intercepting signals</h2>
<p>
libdar by itself does not make use of any signal (see signal(2) and
kill(2)). However, gpgme library with which libdar may be linked with
in order to support asymmetrical strong encryption (i.e. encryption using
public/private keys) may trigger the PIPE signal. Your application
shall thus either ignore it (<code>signal(SIGPIPE, SIG_IGN)</code>)
or provide an adhoc handle.
By default the PIPE signal leads the receiving process to terminate.
</p>
<h2>Libdar classes</h2>
<p>
The main components of libdar are four classes:
</p>
<ul>
<li><b>class libdar::archive</b> to play with dar archives</li>
<li><b>class libdar::database</b> to play with dar_manager databases</li>
<li><b>class libdar::libdar_slave</b> to take the role of dar_slave</li>
<li><b>class libdar::libdar_xform</b> to re-slice existing archives like dar_xform does</li>
</ul>
<p>
In the following we will first see <b>class libdar::archive</b>
which will take most of our effort as other
classes which we will see at the end are very trivial.
</p>
<h2>Multithreaded environment</h2>
<p>
Except when explicitely mentioned,
a given libdar object can only be manipulated by a
single thread. You can however perform several operations
concurrently from different thread, each having its own set
of libdar objects. Though, if one thread is creating an
archive by mean of an first object and at the same
time another thread by mean of a second object is trying to read the
same archive under construction, things might not work as expected. But this
is obvious considerations we will not dig any further assuming you
know what you are doing.
</p>
<h2>Let's create a simple archive</h2>
<p>
Creating a <code>libdar::archive</code> object depending on
the constructor used, leads to either:
</p>
<ul>
<li>
the <b>creation of a brand new archive</b> on filesystem, thus
performing a backup (full, incremental, differential,
decremental, ...)
</li>
<li>
the <b>opening an existing archive</b>, for further
operation (listing, file restoration, archive testing,
archive difference, ...)
</li>
<li>
<b>merging</b> the content of two existing archives into a new one
</li>
<li>
the <b>reparing</b> of an archive which catalogue is missing
or damaged. The <i>catalogue</i>
(which means catalog in French) is the table of content
of an archive.
</li>
</ul>
<h3>Basic archive creation</h3>
<p>
For <b>archive creation</b> the
constructor format is the following one:
</p>
<code class=block>
archive::archive(const std::shared_ptr<user_interaction> & <b>dialog</b>,
const path & <b>fs_root</b>,
const path & <b>sauv_path</b>,
const std::string & <b>filename</b>,
const std::string & <b>extension</b>,
const archive_options_create & <b>options</b>,
statistics * <b>progressive_report</b>);
</code>
<p>
For now we will left beside some parameters, that we will see
in detail later:
</p>
<ul>
<li>
<b>dialog</b> can be set to <b>std::nullptr</b> for now, this means
that all interaction with the user will take place by mean of standard
input, output and error.
</li>
<li>
<b>fs_root</b> is the directory to take as
root of the backup. The <b>libdar::path</b>
class can be setup from a <b>std::string</b>, which
in turn can be setup from a classical <b>char*</b>
</li>
<li>
<b>sauv_path </b> is the path where to
write the archive to, here also a <b>std::string</b>
will do the job
</li>
<li>
<b>filename</b> is the <i>slice name</i> to use for
the archive we will create.
</li>
<li>
<b>extension</b> is the archive extension
to use. There is no reason to not use the string
<b>"dar"</b> here
</li>
<li>
<b>options</b> is a class that carries all
optional parameters, it contains a
<i>constructor without argument</i> setting
all options are set to their default values
</li>
<li>
<b>statistics</b> can
receive the address of an existing object that another thread can read
while a first one is doing a backup operation (a first case of libdar
object that can be used by several threads at the same time). We will see this feature
later on, but for now let's set this to a <b>null pointer</b> (i.e.: std::nullptr)
</li>
</ul>
<p>
Once the object has been created (the constructor has returned), the
archive operation has completed and a new backup has been completely
written on disk.
</p>
<code class=block>
libdar::archive my_first_backup(nullptr,
"/home/me",
"/tmp",
"first_backup",
"dar",
libdar::archive_options_create(),
std::nullptr);
</code>
<p>
The previous example has create a single sliced archive
<b>first_backup.1.dar</b> located under
<b>/tmp</b>. This backup contains the content of
the directory <b>/home/me</b>
and its sub-directories, without compression
and without ciphering. You have guessed: compression,
slicing, ciphering can be set by playing with
passing an adhoc <b>archive_option_create</b>
object to this archive constructor, something we will
see in details a bit further.
</p>
<p>
Once the object <code>my_first_backup</code>
has been created there is only little thing we can do
with it: only archive listing or archive isolation. For archive
extraction, testing or diffing, we needs creating a new object with a
"read" constructor.
<p>
If we had allocated the archive on the heap (using <code>new</code>),
we would have just added the <code>delete</code> invocation right
after the construction of the <code>my_first_backup</code>
object:
</p>
<code class=block>
libdar::archive* my_first_backup = new libdar::archive(nullptr,
"/home/me",
"/tmp",
"first_backup",
"dar",
libdar::archive_options_create(),
nullptr);
// we assume std::bad_alloc would be thrown if an allocation
// problem had occurred
// same thing if libdar throws an exception at constructor time,
// the object would not be created and would not have to be deleted.
// So now we can delete the created object:
delete my_first_backup;
</code>
<h3>Progressive report</h3>
<p>
During the operation we get nothing shown unless an error occurs.
To provide more visibility on the process we will use an
<b>libdar::statistics</b>
object passed as last argument of this constructor. Then we will
use some interesting method of class <class>libdar::statistics</class>:
</p>
<ul>
<li>std::string <b>get_treated_str()</b></li>
<li>std::string <b>get_hard_links_str()</b></li>
<li>std::string <b>get_skipped_str()</b></li>
<li>std::string <b>get_inode_only_str()</b></li>
<li>std::string <b>get_ignored_str()</b></li>
<li>std::string <b>get_tooold_str()</b></li>
<li>std::string <b>get_errored_str()</b></li>
<li>std::string <b>get_deleted_str()</b></li>
<li>std::string <b>get_ea_treated_str()</b></li>
<li>std::string <b>get_byte_amount_str()</b></li>
<li>std::string <b>get_fsa_treated_str()</b></li>
</ul>
<p>
If you have a doubt about the meaning and use of a particular counter
in a particular operation, please refer to <i>API reference documentation</i>
for class <code>libdar::statistics</code>, the private fields
corresponding to these counter are explicitly defined there.
</p>
<code class=block>
<b>libdar::statistics <e>stats</e>;</b>
libdar::archive my_first_backup(nullptr,
"/home/me",
"/tmp",
"first_backup",
"dar",
libdar::archive_options_create(),
<e>& stats</e>);
// in another thread we can see the progression:
std::cout << <e>stats</e>.get_treated_str()
<< " file(s) saved" << std::endl;
std::cout << <e>stats</e>.get_errored_str()
<< " file(s) failed to backup" << std::endl;
std::cout << <e>stats</e>.get_ea_treated_str()
<< " Extended Attributes saved" < std::endl;
</code>
<h3>Archive creation options</h3>
<p>
in the previous example, we
have created an temporary object of class <b>libdar::archive_options_create</b> and
passed it on-fly to the archive constructor without modifying it. Thus
we used the default options for this operations. But <b>a lot</b>
of options are available, each one can be modified by a specific
method of this class Follow is a subset of the
available options. We won't details them all, but you can refer the doxygen
documentation for <b>class libdar::archive_options_create</b> for additional information.
</p>
<ul>
<li><code>void <b>set_reference</b>(<b>std::shared_ptr<libdar::archive></b> ref_arch)</code></li>
<li><code>void <b>set_selection</b>(const <b>libdar::mask</b> & selection)</code></li>
<li><code>void <b>set_subtree</b>(const <b>libdar::mask</b> & subtree)</code></li>
<li><code>void <b>set_allow_over</b>(bool allow_over)</code></li>
<li><code>void <b>set_warn_over</b>(bool warn_over)</code></li>
<li><code>void <b>set_info_details</b>(bool info_details)</code></li>
<li><code>void <b>set_display_treated</b>(bool display_treated, bool only_dir)</code></li>
<li><code>void <b>set_display_skipped</b>(bool display_skipped)</code></li>
<li><code>void <b>set_display_finished</b>(bool display_finished)</code></li>
<li><code>void <b>set_pause</b>(const <b>libdar::infinint</b> & pause)</code></li>
<li><code>void <b>set_empty_dir</b>(bool empty_dir)</code></li>
<li><code>void <b>set_compression</b>(<b>libdar::compression</b> compr_algo)</code></li>
<li><code>void <b>set_compression_level</b>(<b>libdar::U_I</b>compression_level)</code></li>
<li><code>void <b>set_slicing</b>(const <b>libdar::infinint</b> & file_size, const <b>libdar::infinint</b> & first_file_size)</code></li>
<li><code>void <b>set_ea_mask</b>(const <b>libdar::mask</b> & ea_mask)</code></li>
<li><code>void <b>set_execute</b>(const std::string & execute)</code></li>
<li><code>void <b>set_crypto_algo</b>(<b>libdar::crypto_algo</b>crypto)</code></li>
<li><code>void <b>set_crypto_pass</b>(const <b>libdar::secu_string</b> & pass)</code></li>
<li><code>void <b>set_compr_mask</b>(const <b>libdar::mask</b> & compr_mask);</code></li>
<li><code>void <b>set_min_compr_size</b>(const <b>libdar::infinint</b> & min_compr_size)</code></li>
<li><code>void <b>set_nodump</b>(bool nodump)</code></li>
<li><code>void <b>set_exclude_by_ea</b>(const std::string & ea_name)</code></li>
<li><code>void <b>set_what_to_check</b>(<b>libdar::comparison_fields</b> what_to_check)</code></li>
<li><code>void <b>set_hourshift</b>(const <b>libdar::infinint</b> & hourshift)</code></li>
<li><code>void <b>set_empty</b>(bool empty)</code></li>
<li><code>void <b>set_alter_atime</b>(bool alter_atime)</code></li>
<li><code>void <b>set_furtive_read_mode</b>(bool furtive_read)</code></li>
<li><code>void <b>set_same_fs</b>(bool same_fs)</code></li>
<li><code>void <b>set_snapshot</b>(bool snapshot)</code></li>
<li><code>void <b>set_cache_directory_tagging</b>(bool cache_directory_tagging)</code></li>
<li><code>void <b>set_fixed_date</b>(const <b>libdar::infinint</b> & fixed_date)</code></li>
<li><code>void <b>set_slice_permission</b>(const std::string & slice_permission)</code></li>
<li><code>void <b>set_slice_user_ownership</b>(const std::string & slice_user_ownership)</code></li>
<li><code>void <b>set_slice_group_ownership</b>(const std::string & slice_group_ownership)</code></li>
<li><code>void <b>set_retry_on_change</b>(const <b>libdar::infinint</b> & count_max_per_file, const <b>libdar::infinint</b> & global_max_byte_overhead)</code></li>
<li><code>void <b>set_security_check</b>(bool check)</code></li>
<li><code>void<b> set_user_comment</b>(const std::string & comment)</code></li>
<li><code>void <b>set_hash_algo</b>(<b>libdar::hash_algo</b> hash)</code></li>
<li><code>void <b>set_slice_min_digits</b>(<b>libdar::infinint</b> val)</code></li>
<li><code>void <b>set_backup_hook</b>(const std::string & execute, const <b>mask</b> & which_files);</code></li>
<li><code>void <b>set_delta_diff</b>(bool val)</code></li>
<li><code>void <b>set_delta_signature</b>(bool val)</code></li>
<li><code>void <b>set_delta_mask</b>(const <b>libdar::mask</b> & delta_mask)</code></li>
</ul>
<p>
First you may have find some new libdar types (=classes) in arguments, we will
briefly explain how to set them:
</p>
<dl>
<dt class=void>std::shared_ptr<libdar::archive></dt><dd>
<p>
C++11 shared smart-pointer to an existing libdar::archive object. We will see
how to use it next when performing differential backup
</p>
</dd>
<dt class=void>libdar::infinint</dt><dd>
<p>
can be set from a <b>classical unsigned int</b>,
unsigned long or other unsigned integer type, so
for you this is like another unsigned integer type
</p>
</dd>
<dt class=void>libdar::mask</dt><dd>
<p>
This class is a top of a class hierarchy containing
several classes provided with libdar. It allows you
to define a filtering mecanism for the feature wher
it is used. We will see how to use it in a further
paragraph of this tutorial.
</p>
</dd>
<dt class=void>libdar::compression</dt><dd>
<p>
It is an enumeration which values are (among others
not listed here):
</p>
<ul>
<li><code>libdar::compression::<b>gzip</b></code></li>
<li><code>libdar::compression::<b>bzip2</b></code></li>
<li><code>libdar::compression::<b>xz</b></code></li>
<li><code>libdar::compression::<b>lzo</b></code></li>
</ul>
<br/>
</dd>
<dt class=void>libdar::U_I</dt><dd>
<p>
A the opposite of the libdar::infinint this is not a class
but an alias to the system classical unsigned integer. Depending
on the operating system and CPU this might point to <i>unsigned long</i>
or <i>unsigned long long</i> or other equivalent type.
</p>
</dd>
<dt class=void>libdar::crypto_algo</dt><dd>
<p>
This is an enumeration with values like:
</p>
<ul>
<li><code>libdar::crypto_algo::<b>scrambling</b></code></li>
<li><code>libdar::crypto_algo::<b>blowfish</b></code></li>
<li><code>libdar::crypto_algo::<b>aes256</b></code></li>
<li><code>libdar::crypto_algo::<b>twofish256</b></code></li>
<li><code>libdar::crypto_algo::<b>serpent256</b></code></li>
<li><code>libdar::crypto_algo::<b>camellia256</b></code></li>
</ul>
<br/>
</dd>
<dt class=void>libdar::secu_string</dt><dd>
<p>
This is a class used to securely storing password and sensible
cryptographic information. It can be setup from a char* or
better, from a filedescriptor. its main constructor is:
</p>
<ul>
<li>secu_string(<b>const char*</b> ptr, U_I <b>size</b>)</li>
</ul>
<br/>
</dd>
<dt class=void>libdar::comparison_fields</dt><dd>
<p>
This is an enumeration with values like:
</p>
<ul>
<li><code>libdar::comparison_fields::<b>all</b></code></li>
<li><code>libdar::comparison_fields::<b>ignore_owner</b></code></li>
<li><code>libdar::comparison_fields::<b>mtime</b></code></li>
<li><code>libdar::comparison_fields::<b>inode_type</b></code></li>
</ul>
</dd>
</dl>
<p>
Follows a variant of the previous backup creation example,
here we set some options to a given value:
</p>
<code class=block>
libdar::archive_options_create <b>opt</b>;
<b>opt</b>.set_allow_over(false);
// forbids slice overwriting
<b>opt</b>.set_display_finished(true);
// show a summary after each completed directory
<b>opt</b>.set_slicing(1024000,
2000);
// slices of 1000 kiB initial slice of 2000 bytes
<b>opt</b>.set_pause(2);
// pause every two slices
<b>opt</b>.set_execute("echo slice %N completed");
// command executed after each slice
<b>opt</b>.set_crypto_algo(libdar::crypto_algo::aes256);
// providing an empty secu_string leads dar
// interactively ask the passphrase in a secure manner
<b>opt</b>.set_crypto_pass(secu_string());
// But this previous call is useless as en empty secu_string is the default
// though one could have setup a secu_string from a std::string
// this way:
std::string my_pass("hello world!");
libdar::secu_string my_secupass(my_pass.c_str(), my_pass.size());
<b>opt</b>.set_crypto_pass(my_secupass);
<b>opt</b>.set_compression(libdar::compression::xz);
<b>opt</b>.set_compression_level(6);
<b>opt</b>.set_min_compr_size(10240);
// not trying compressing file smaller than 10 kiB
// now we have the <b>opt</b> option object ready
// we can proceed to the archive creation using it:
libdar::archive my_first_backup(nullptr,
"/home/me",
"/tmp",
"first_backup",
"dar",
<b>opt</b>,
nullptr);
</code>
<p>
And of course, you can use both <b>libdar::statistics</b>
and <b>libdar::archive_options_create</b> at
the same time, when creating a backup
</p>
<h2>Creating a differential or incremental backup</h2>
<p>
Maybe you have guessed?
Compared to the previous operation (full backup) doing an differential
or incremental backup will only ask to open, in read mode, an existing
archive and pass this object as argument of class
archive_options_create::set_reference() seen just above.
</p>
<p>
The read-only constructor for class archive is the following:
</p>
<code class=block>
archive::archive(const std::shared_ptr<user_interaction> & <b>dialog</b>,
const path & <b>chem</b>,
const std::string & <b>basename</b>,
const std::string & <b>extension</b>,
const archive_options_read & <b>options</b>);
</code>
<p>
same as before:
</p>
<ul>
<li>
<b>dialog</b> can be set to a <b>null pointer</b>, we will see
further in this tutorial how to play with
<code>user_interaction</code> class
</li>
<li>
<b>chem</b> is the path leading to the
archive to read, it can be provided as a <b>std::string</b> or
even a <b>char*</b>
</li>
<li>
<b>basename</b> is the archive basename to read
</li>
<li>
<b>extension</b> should be <b>"dar"</b> unless you want
to confuse people
</li>
<li>
<b>options</b> can be set to an empty object for default
options, we will see this class in more
details with archive listing
</li>
</ul>
<br/>
<code class=block>
// first we open the previously created archive in read mode:
std::shared_ptr<libdar::archive> <e>ref_archive</e>;
<e>ref_archive</e> = std::make_shared<libdar::archive>(nullptr,
"/home/me",
"first_backup",
"dar",
archive_create_options_read());
// for clarity we separated the creation of the
// archive object used as archive of reference from
// the archive object which creation will perform
// differential backup (see below). We could have made
// in one step using an anonymous temporary object
// (in place of <code>ref_archive</code>)
// invoking directly <code>std::make_shared</code>
// when calling <code>set_reference()</code> below:
libdar::archive_options_create <b>opt</b>;
<b>opt</b>.set_reference(<e><b>ref_archive</b></e>);
libdar::archive my_second_backup(nullptr,
"/home/me",
"/tmp",
"diff_backup",
"dar",
<b>opt</b>,
nullptr);
</code>
<p>
creating a
incremental backup is exactly the same, the difference is the nature of
the archive of reference. We used to describe a differential backup
one that has a full backup as reference, while an incremental backup
has another incremental or differential backup as reference (not a full
backup).
</p>
<h2>Archive listing</h2>
<p>
Archive listing operation consist of the creation of an archive object
in read mode as we just did above for <code>ref_archive</code> and
invoking a method on that newly object to see all or a sub-directory
content of the archive. Before
looking at the listing method let's zoom on the class
<code>libdar::archive_create_options_read</code> which
we just skip over previously.
</p>
<h3>Archive reading options</h3>
<p>
The same as the class <code>archive_options_create</code> detailed above, the
class <code>archive_options_read</code> has a constructor without argument that sets
the different options to their default value. You can change them one
by one by mean of specific methods. The most usual ones are:
</p>
<ul>
<li>void <b>set_execute</b>(const std::string & execute)</li>
<li>void <b>set_info_details</b>(bool info_details)</li>
<li>void <b>set_sequential_read</b>(bool val)</li>
<li>void <b>set_slice_min_digits</b>(infinint val)</li>
</ul>
<p>
<code>set_execute()</code> runs a command before reading a new slice of the
archive. See API reference documentation for details. You will meet
class <code>archive_options_create</code> in order to test an archive,
compare an archive with filesystem, isolate an archive and repair an archive.
</p>
<h3>Listing methods</h3>
<p>
There is several ways to read an given archive contents:
</p>
<ol>
<li>
<p>
making use of a callback function that will be called in turn
for <u>each entry of the archive</u> even special entries that
flag the end of a directory and the next entry will be located in the parent directory:
</p>
<code class=block>
void <b>op_listing</b>(libdar::archive_listing_callback <b>callback</b>,
void *<b>context</b>,
const libdar::archive_options_listing & <b>options</b>) const;
</code>
</li>
<li>
<p>
using the same callback but only for the different <u>entries of a given directory</u>,
directory that has to exist in the archive of course. It returns false
when the end of the directory has been reached:
</p>
<code class=block>
bool <b>get_children_of</b>(libdar::archive_listing_callback <b>callback</b>,
void *<b>context</b>,
const std::string & <b>dir</b>,
bool <b>fetch_ea</b> = false);
</code>
</li>
<li>
<p>
like previous <u>listing a given directory content</u> but returning
a vector of objects <b>libdar::list_entry</b> that provide
detailed information about each entry, no callback is used here:
</p>
<code class=block>
const std::vector<libdar::list_entry> <b>get_children_in_table</b>(const std::string & dir,
bool <b>fetch_ea</b> = false) const;
</code>
</li>
</ol>
<p>
<b>For the two first methods</b>
you have to define a callback function of the following form:
</p>
<code class=block>
void (*)(const std::string & the_path,
const list_entry & entry,
void *context);
</code>
<p>
This callback will receive as argument the full path of the object,
a <b>libdar::list_entry</b> object providing
much details on it <b>and</b> the "context" value passed as argument
of <b>archive::op_listing()</b> or <b>archive::get_children_of()</b>
</p>
<p>
In the following example we will use only a few methods of
class <b>libdar::list_entry</b> that are available to get detail
of a given entry of an archive, feel free to explore this class's
documentation for to get all details:
</p>
<code class=block>
// we first create a read-mode archive object that will be used
// in the three following examples,
libdar::archive_options_read opt;
opt.set_info_details(true);
opt.set_execute("echo 'about to read slice %p/%b.%N.%e with context %c'");
libdar::archive <b>my_backup</b>(nullptr, // this is user_interaction we will see further
"/home/me",
"diff_backup",
"dar",
opt);
</code>
<br/>
<code class=block>
// we will also illustrate here the use of libdar::archive_options_read
// inside the callback function we will define here:
void <b>my_listing_callback</b>(const std::string & the_path,
const libdar::list_entry & entry,
void *context)
{
std::cout << the_path;
if(entry.is_dir())
std::cout << " is a directory";
std::cout << " with permission " << entry.get_perm();
std::cout << " file located in slices " << entry.get_slices().display();
std::cout << std::endl;
// yep, we do not need context, this
// is available if you need it though
if(entry.is_eod())
{
// only op_listing() provides such type of object
// which occurs when we reached the <b>E</b>nd <b>O</b>f <b>D</b>irectory
// next entry will be located in the parent directory.
//
// Note for op_listing: when reading a directory we recurs in it,
// meaning that the next entry this callback will be
// invoked for will be located in that directory
//
// for get_children_of() no recursion or eod object is
// performed about directory. The next entry following
// a directory is still located in the same parent directory
// which when fully read stops the get_children_of() routine
// at the difference of op_listing() which parse the whole
// directory tree.
//
// For example, reading a empty directory will provide
// that directory info, then an eod object a the next
// callback invocation.
}
}
</code>
<p>
These two objects <code>my_backup</code> and <code>my_listing_callback()</code>
we just defined will be used in the following examples.
</p>
<h3>Archive listing using archive::op_listing()</h3>
<p>
<u>First possibility:</u> we can pass nullptr as callback function to
archive::op_listing, all will be displayed in stdout
</p>
<code class=block>
<b>my_backup</b>.op_listing(<b>nullptr</b>, // no callback function
nullptr, // we don't use the context here
archive_options_listing()) // and use default listing options
</code>
<p>
<u>Second possibility:</u> we use the callback defined previously:
</p>
<code class=block>
<b>my_backup</b>.op_listing(<b>my_listing_callback</b>,
nullptr, // we still don't use the context here
archive_options_listing()) // and still the default listing options
</code>
<p>
In complement of both previous variant we can of course set non default listing options
</p>
<code class=block>
libdar::archive_options_listing <b>opt</b>;
<b>opt</b>.set_filter_unsaved(true);
// skip entry that have not been saved since the archive of reference
<b>opt</b>.set_slice_location(true);
// necessary if we want to have slicing information available in the callback function
opt.set_fetch_ea(false);
// this is the default. Set it to true if you
// want to use list_entry::get_ea_reset_read()/get_ea_next_read()
<b>my_backup</b>.op_listing(my_listing_callback,
nullptr, // we still don't care of context here
<b>opt</b>); // and still the default listing options
</code>
<h3>Archive listing using archive::get_children_of()</h3>
<code class=block>
// With this method we only list one directory
my_backup.<b>get_children_of</b>(my_listing_callback,
nullptr, // we still don't care of context here
<b>"",</b> // we read the root directory of the archive
true); // and ask for EA retrieval, but as we do not
// use list_entry::get_ea_read_next() in the
// callback this is just wasting CPU and memory
// or course if you have a sub-directory /home/me/.gnupg/private-keys-v1.d
// in your home directory and you want to check how it is saved in the
// archive, as we defined the root of the backup as /home/me and as you
// always have to pass a relative path (no leading /) you could do that by
// calling the following:
my_backup.<b>get_children_of</b>(my_listing_callback,
nullptr,
<b>".gnupg/private-keys-v1.d"</b>);
</code>
<h3>Archive listing using archive::get_children_in_table()</h3>
<code class=block>
// still listing a single directory but this time without callback function:
my_backup.<b>init_catalogue</b>();
// necessary to fill read the whole catalogue in memory
// in particular if archive has been opened in sequential read mode
std::vector<libdar::list_entry> result = my_backup.<b>get_children_in_table</b>(".gnupg/private-keys-v1.d");
// now reading the std::vector
std::vector<libdar::list_entry>::iterator it = result.begin();
while(it != result.end())
{
if(it->is_dir())
std::cout << " is a directory";
std::cout << " with permission " << it->get_perm();
std::cout << " located in slices " << it->get_slices().display();
std::cout << std::endl;
}
</code>
<h2>Testing an archive</h2>
<p>
As seen for listing operation
we assume a archive object has been create in read mode. Testing the
coherence of the relative archive files on disk is done by calling the <b>libdar::op_test</b> method:
</p>
<code class=block>
libdar::statistics op_test(const libdar::archive_options_test & options,
libdar::statistics * progressive_report);
</code>
<p>
You may have recognized the
<code>libdar::statistics</code> type we saw for archive creation. It is present as
argument and the provided libdar::statistics object can be read during
the whole testing operation by another thread. But if you just want the
to know the result, you'd better just use the returned value as it
makes the operation quicker due to the absence of multithread
management.
</p>
<code class=block>
// for the exercise, we will change some default options:
archive_options_test <b>opt</b>;
<b>opt</b>.set_info_details(true); // to have a verbose output
libdar::statistics <b>stats</b>;
<b>stats</b> = my_backup.<b>op_test</b>(nullptr, // still the user_interaction we will see further
<b>opt</b>; // the non default options set above
nullptr); // we will just use the returned value
std::cout << <b>stats</b>.get_treated_str() << "file(s) tested" << std::endl;
std::cout << <b>stats</b>.get_errored_str() << " file(s) with errors" << std::endl;
std::cout << <b>stats</b>.get_ea_treated_str() << " Extended Attributes tested" << std::endl;
</code>
<h2>Comparing an archive</h2>
<p>
As simple as previously, but using the <b>archive::op_diff</b> method:
</p>
<code class=block>
statistics op_diff(const path & fs_root,
const archive_options_diff & options,
statistics * progressive_report);
</code>
<br>
<p>
Over the type of the option
field, you see the <b>fs_root</b> argument
which define which directory of the filesystem to compare the archive to
</p>
<code class=block>
// for the exercise, we will change some default options:
archive_options_diff <b>opt</b>;
<b>opt</b>.set_info_details(true); // to have a verbose output
<b>opt</b>.set_what_to_check(libdar::comparison_fields::ignore_owner);
// this option above will consider equal two files which
// only change due to user or group ownership difference
// by default any difference will be considered a difference
(void)my_backup.<b>op_diff</b>(<b>"/home/me"</b>,
<b>opt</b>; // the non default options set above
nullptr); // not using it for this example
</code>
<h2>Isolating an archive</h2>
<p>
Still as simple as previously, but
using the <b>archive::op_isolate </b>method:
</p>
<code class=block>
void op_isolate(const path &sauv_path,
const std::string & filename,
const std::string & extension,
const archive_options_isolate & options);
</code>
<p>
You will find similitude with the archive creation though here this is not a constructor
</p>
<ul>
<li>
<b>sauv_path </b>is the directory where to create the isolated version of the current archive
</li>
<li><b>filename</b> is the archive basename to create</li>
<li><b>extension</b> should still be "dar" here too</li>
<li>
<b>options</b> are options for isolation like slicing, compression,
encryption similar to the archive_options_create class we saw at
the beginning of this tutorial
</li>
</ul>
<code class=block>
// for the exercise, we will change some default options:
archive_options_isolate <b>opt</b>;
<b>opt</b>.set_warn_over(false);
// by default overwriting is allowed by a warning is issued first
// here overwriting will take place without warning
<b>opt</b>.set_compression(libdar::compression::gzip);
<b>opt</b>.set_compression_level(9);
// this is the default
<b>opt</b>.set_min_compr_size(10240);
// not trying compressing file smaller than 10 kiB
my_backup.<b>op_isolate</b>("/tmp",
"CAT_diff_backup",
"dar",
<b>opt</b>); // the non default options set above
// have you noted? There is no libdar statistics field returned nor as argument.
</code>
<h2>Restoring files from an archive</h2>
<p>
Quite as simple as previously, here we use the <b>archive::op_extract</b>method:
</p>
<code class=block>
statistics op_extract(const path & fs_root,
const archive_options_extract & options,
statistics *progressive_report);
</code>
<p>
<ul>
<li><b>fs_root</b> is the directory under which to restore the files and directory</li>
<li><b>options</b> defines how and what to restore</li>
<li><b>progressive_report</b> has already been seen several time previously</li>
</ul>
</p>
<code class=block>
// as we still do not have seen masks, we will restore all files contained in the backup<br>
// such mask would be provided to the <br>
// archive_options_extract::set_selection() and/or <br>
// to the archive_options_extract::set_subtree() methods<br>
// to precisely define what files to restore<br>
archive_options_extract <b>opt</b>;
<b>opt</b>.set_dirty_behavior(false, false); // dirty files are not restored
(void) my_backup.<b>op_extract</b>("/home/me/my_home_copy",
<b>opt</b>,
nullptr); // we have seen previously how to use statistics
</code>
<h2>Merging archives</h2>
<p>
Here we will need two archive objects open in read-mode and we will invoke a
specific archive constructor passing these two objects as argument,
once the constructor will have completed the merging operation will be
done.
</p>
<code class=block>
archive(const std::shared_ptr<user_interaction> & dialog,
const path & sauv_path,
std::shared_ptr<archive> ref_arch1,
const std::string & filename,
const std::string & extension,
const archive_options_merge & options,
statistics * progressive_report);
</code>
<p>
<ul>
<li><b>dialog</b> is will still be set to null pointer for now</li>
<li><b>sauv_path</b> is the directory where to create the resulting merging archive</li>
<li>
<b>ref_arch1</b> is the first (and mandatory) archive,
the second is optional and may be given to the <b>options</B> argument
</li>>
<li><b>filename</b> is the resulting archive basename</li>
<li><b>extension</b> as always should be set to "dar"</li>
<li><b>options</b> is a set of optional parameters</li>
<li>
<b>progressive_report</b> is as seen above the ability
to have another thread showing progression info during the operation
</li>
</ul>
</p>
<code class=block>
// assuming you have two backups:
// the first is /tmp/home_backup.*.dar
// the second is /var/tmp/system_backup.*.dar
// we will create /tmp/merged.*.dar as result of the merging
// of these two backups
// 1 - first things first: opening the first backup
libdar::archive_options_read <b>opt</b>;
<b>opt</b>.set_info_details(true);
<b>opt</b>.set_execute("echo 'about to read slice %p/%b.%N.%e with context %c'");
std::shared_ptr<libdar::archive> <b>home_backup</b>(<b>new</b> libdar::archive(nullptr, // this is user_interaction we'll see further
"/tmp",
"home_backup",
"dar",
<b>opt</b>));
// 2 - opening the second backup
std::shared_ptr<libdar::archive> <b>system_backup</b>(<b>new</b> libdar::archive(nullptr,
"/var/tmp",
"system_backup",
"dar",
<b>opt</b>);
// 3 - setting up the options for merging operation
libdar::archive_options_merge <b>opt_merge</b>;
opt_merge.set_auxiliary_ref(<b>system_backup</b>);
// while merging the second backup is optional, where from the use of option for it
opt_merge.set_slicing(1048576, 0); // all slice would have 1 MiB at most
opt_merge.set_compression(libdar::compression::bzip2);
opt_merge.set_keep_compressed(true);
opt_merge.set_user_comment("archive resulting of the merging of home_backup and system_backup");
opt_merge.set_hash_algo(libdar::hash_algo::sha512); // will generate on-fly hash file for each slice
// 4 - now performing the merging operation<br>
libdar::archive <b>merged</b>(nullptr, // still the user_interaction we will see further
"/tmp",
<b>home_backup</b>, // first back is mandatory, not part of options
"merged",
"dar",
<b>opt_merge</b>,
nullptr); // progressive_report, we don't use here
</code>
<h2>Decremental backup</h2>
<p>
Decremental backup is an operation that, from two full backups, an old and a recent
one, creates a backward differential backup corresponding to the old
full backup, which difference is based on the new full backup. In other words, instead of
keeping two full backups, you can keep the latest and replace the
oldest by its decremental counterpart. This will save you space while
letting you restore as if you had the old full backup by restoring
first the recent (full) backup then the decremental backup.
</p>
<p>
Creating a decremental backup is exactly the same as creating a merging
backup, you need just to set the
<code>archive_options_merge::set_decremental_mode()</code> before proceeding to the
merging. To avoid duplication we will just illustrate the last step of
the previous operation modified for decremental backup:
</p>
<code class=block>
// creating the two read-only backup as for merging operation
// the only difference is that here both backups are mandatory
std::shared_ptr<libdar::archive> <b>old_full_backup</b>(...); // not detailing this part
std::shared_ptr<libdar::archive> <b>new_full_backup</b>(...); // not detailing this part
// setting up the options for a decremental operation
libdar::archive_options_merge <b>opt_merge</b>;
opt_merge.<b>set_decremental_mode</b>(true);
opt_merge.set_auxiliary_ref(<b>new_full_backup</b>);
// now performing the merging operation (here decremental backup)
libdar::archive merged(nullptr, // still the user_interaction we will see further
"/tmp",
<b>old_full_backup</b>,
"decremental_backup",
"dar",
<b>opt_merge</b>,
nullptr); // progressive_report we don't use here
</code>
<h2>Archive repairing</h2>
<p>
If an archive has been truncated due to lack of disk space and if
sequential marks (aka tape marks) had not been disable, it is possible
to rebuild sane archive beside this truncated one.
</p>
<p>
We just need to invoke a <b>specific libdar::archive constructor</b>
which form follows:
</p>
<code class=block>
archive(const std::shared_ptr<user_interaction> & dialog,
const path & chem_src,
const std::string & basename_src,
const std::string & extension_src,
const archive_options_read & options_read,
const path & chem_dst,
const std::string & basename_dst,
const std::string & extension_dst,
const archive_options_repair & options_repair);
</code>
<p>
You should now be familiarized with the different types and variable
uses. As you can note, this constructor takes in charge the work to
read the damaged archive because if the archive is corrupted a normal
constructor would fail, so you won't have to do it first. As always,
this constructor will end only once the operation will have completed,
that's to say at the end of the reparing.
</p>
<code class=block>
// assuming the archive /tmp/home_backup.*.dar is damaged
// and you want to have repaired archive as /tmp/home_backup_repaired.*.dar
libdar::archive repaired(nullptr, // still the user_interaction we have not yet seen
"/tmp"
"home_backup",
"dar",
<b>archive_options_read()</b>,
"/tmp",
"home_backup_repaired",
"dar",
<b>archive_options_repair()</b>);
// we have not done fancy things with the two option classes, but we did above
// enough time for you get all the necessary information from the API reference
// documentation
</code>
<h2>Looking at some details</h2>
<p>
we have covered the different operations the class <code>libdar::archive</code>
can be used for, still remains some concepts to view:
</p>
<ul>
<li>user_interaction</li>
<li>masks</li>
<li>how to cleanly interrupt an running libdar routine</li>
<li>how to known which compile-time feature has been activated</li>
</ul>
<p>
Then we will see the three other more simple classes:
</p>
<ul>
<li>class database</li>
<li>class libdar_slave</li>
<li>class libdar_xform</li>
</ul>
<p>
This will be the subject of the following chapters, but for now,
maybe you remember that we had to initialize libdar before use,
by calling <code>libdar::get_version()</code>?
This routine also exists with arguments that will provide as
its name suggests the libdar version:
</p>
<code class=block>
void get_version(U_I & major, U_I & medium, U_I & minor, bool init_libgcrypt = true);
</code>
<p>
It is advised to use this form to fetch the libdar version major,
medium and minor numbers to be sure the library
you've dynamically linked with is compatible with the features you will
be using:
</p>
<ul>
<li>
The <b>major</b> number must be the same, because no compatibility is
assured between two libdar versions of different major numbers.
</li>
<li>
While run-time compatibility is assured between <b>medium</b> numbers,
the medium number must be greater or equal to the one used at
compilation time to be sure that all the features you want are
available in the libdar library you dynamically linked with.
</li>
<li>
Changes between <b>minor</b> versions correspond to bug fixes and
does not to imply any API change, thus no constraints is present
there (just note the presence of more bugs in lower numbers).
</li>
</ul>
<p>
<b>If you use libgcrypt beside libdar</b> in your application you should
initialize libgcrypt and not let it be done by libdar the latest
argument of this form should be set to false in that case, according to the
<a href="https://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html#Initializing-the-library">libgcrypt documentation</a>
which indicates that <i>libgcrypt</i> should normally (always) be initialized directly
from the application not from an intermediate library.
</p>
<p>
Follows an example of test that can be performed while initializing libdar:
</p>
<code class=block>
U_I major, medium, minor;
libdar::get_version(major, medium, minor);
if(maj != libdar::LIBDAR_COMPILE_TIME_MAJOR ||
med < libdar::LIBDAR_COMPILE_TIME_MEDIUM)
{
std::cout << "libdar version we link with is too old for this code" << std::endl;
// throw an exception or anything else appropriate to that condition:
throw "something";
}
</code>
<br/>
<h2>Checking compile-time features activation</h2>
<p>
Once we have called one of the <code>get_version*</code>
function it is possible to access the list of features activated at
compilation time thanks to a set of function located in the
<code>compile_time</code> nested namespace inside libdar:
</p>
<code class=block>
void my_sample_function()
{
bool ea = libdar::compile_time::ea();
bool largefile = libdar::compile_time::largefile();
bool nodump = libdar::compile_time::nodump();
bool special_alloc = libdar::compile_time::special_alloc();
U_I bits = libdar::compile_time::bits();
// bits is equal to zero for infinint,
// else it is equal to 32 or 64 depending on
// the compilation mode used.
bool thread = libdar::compile_time::thread_safe();
bool libz = libdar::compile_time::libz();
bool libbz2 = libdar::compile_time::libbz2();
bool liblzo = libdar::compile_time::liblzo();
bool libxz = libdar::compile_time::libxz();
bool libcrypto = libdar::compile_time::libgcrypt();
bool furtive_read = libdar::compile_time::furtive_read();
// for details see the compile_time namespace in the API reference documentation
}
</code>
<h2>User Interaction</h2>
<p>
we have seen <code>std::shared_pointer</code> on class <b>libdar::user_interaction</b>
previously but did not used this feature.
</p>
<h3>Defining your own user_interaction class</h3>
<p>
class <b>libdar::user_interaction</b>
defines the way libdar interact with the user during an operation, like
an archive creation, restoration, testing and so on. Only four types of
interaction are used by libdar:
</p>
<code class=block>
void <b>message</b>(const std::string & message);
void <b>pause</b>(const std::string & message);
std::string <b>get_string</b>(const std::string & message, bool echo);
secu_string <b>get_secu_string</b>(const std::string & message, bool echo);
</code>
<p>
By default an inherited class of <code>libdar::user_interaction</code>, called
<code><b>libdar::shell_interaction</b></code>, is used and implements these
four type of exchange by mean of text terminal:
</p>
<ul>
<li><b>message()</b> sends the std::string provided by libdar to stdout</li>
<li><b>pause()</b> does the same and ask for the user to press either return or escape to answer yes or no</li>
<li><b>get_string()</b> reads a string from stdin</li>
<li><b>get_secu_string()</b> reads a string into a secu_string object from stdin too<br>
</li>
</ul>
<p>
For a GUI you will probably not want stdin and stdout to be used.
Instead of that you have the possibility to implement your own inherited class
from user_interaction. This one should look like the following:
</p>
<code class=block>
class my_user_interaction: public libdar::user_interaction
{
protected:
// display of informational message
virtual void <b>inherited_message</b>(const std::string & message) override;
// display of a question and returns the answer from user as true/false
virtual bool <b>inherited_pause</b>(const std::string & message) override;
// display the message and returns a string from the user,
// with or without display what the user typed (echo)
virtual std::string <b>inherited_get_string</b>(const std::string & message, bool echo) override;
// same as the previous be the user provided string is returned as secu_string
virtual libdar::secu_string <b>inherited_get_secu_string</b>(const std::string & message, bool echo) override;
};
</code>
<h3>Relying on the pre-defined user_interaction_callback class</h3>
<p>
As an alternative to defining
your own inherited class from <code>libdar::user_interaction</code>,
libdar provides a class called <code>user_interaction_callback</code>
which is an implementation of the user interaction, based on callback
functions.
</p>
<p>
You will need to implement four callback functions:
</p>
<code class=block>
using <b>message_callback</b> = void (*)(const std::string &x, void *context);
using <b>pause_callback</b> = bool (*)(const std::string &x, void *context);
using <b>get_string_callback</b> = std::string (*)(const std::string &x, bool echo, void *context);
using <b>get_secu_string_callback</b> = secu_string (*)(const std::string & x, bool echo, void *context);
</code>
<p>
Then you can create an libdar::user_interaction_callback object using this constructor:
</p>
<code class=block>
user_interaction_callback(<b>message_callback</b> x_message_callback,
<b>pause_callback</b> x_answer_callback,
<b>get_string_callback</b> x_string_callback,
<b>get_secu_string_callback</b> x_secu_string_callback,
void *context_value);
</code>
<p>
Here follows an example of use:
</p>
<code class=block>
void <b>my_message_cb</b>(const std::string & x, void *context)
{
std::cout << x << std::endl;
}
bool void <b>my_pause_cb</b>(const std::string & x, void *context)
{
char a;
std::cout << x << endl;
std::cin >> a;
return a == 'y';
}
std::string <b>my_string_cb</b>(const std::string & x, bool echo, void *context)
{
// to be defined
}
libdar::secu_string <b>my_secu_string_cb</b>(const std::string & x, bool echo, void *context)
{
// to be defined
}
// eventually using a context_value that will be passed to the callback of the object
void *context_value = (void *)(& some_datastructure);
std::shared_ptr<libdar::user_interaction> my_user_interaction(new libdar::user_interaction_callback(<b>my_message_cb</b>,
<b>my_pause_cb</b>,
<b>my_string_cb</b>,
<b>my_secu_string_cb</b>,
context_value));
</code>
<p>
You can also find the predefined classes <b>libdar::user_interaction_blind</b>
which always says no in name of the user displays nothing and provide empty strings,
as well as <b>libdar::shell_interaction_emulator</b>
which given a user_interaction object send to it the formatted information
as if it was a shell_interaction object, leading one to emulate libdar
default behavior under any type of "terminal".
</p>
<dl>
<dt class=void>IMPORTANT</dt><dd>
all <code>libdar::user_interaction</code> inherited classes
provided by libdar are not designed to be manipulated by more
than one thread at a time. The use of <code>std::shared_ptr</code>
is only here to let the caller not have to manage
such object and let libdar release it when no more needed <b>or</b>
to let the caller reuse the same user_interaction object for a
subsequent call to libdar which would not be possible if a
<code>std::unique_ptr</code> was used instead.
</dd>
</dl>
<p>
Now if you design your own <i>user_interaction inherited class</i>
and provide them mecanism (mutex, ...) that allow them to be used
simultaneously by several thread there is no issue to pass a such object as
argument to different libdar object used by different threads running at the
same time.
</p>
<h2>Masks</h2>
<p>
Mask are used to define which <u>string</u>
will be considered and which will not. Libdar implements masks as
several classes that all inherit from a virtual class named
<code>libdar::mask</code> that defines the way masks are used
(interface class). This class defines the
<code>bool mask::is_covered(const std::string & expression) const</code> method
which libdar uses to determine whether a given string matches or
not a mask and thus whether the corresponding entry (filename, EA, directory path
depending on the context), is eligible or not for an operation.
</p>
<p>
Strings applied to masks may correspond to filename only, to full path
or maybe to other things (like Extended Attributes). That's in the
context where the mask is used that the string meaning take place,
thing we will see further.
</p>
<p>
There is several different basic masks classes you can use
to build fairly complex masks, while it is possible you should
not need to define you own mask classes, if the need arises,
please contact libdar developer if you thing an additional class
should take place beside the following ones:
</p>
<div class=table>
<table>
<tr>
<th>
class name
</th>
<th>
behavior
</th>
</tr>
<tr>
<td>
class libdar::bool_mask
</td>
<td>
boolean mask, either always true
or false (depending on the boolean passed
at its constructor), it matches either all
or none of the submitted strings
</td>
</tr>
<tr>
<td>
class libdar::simple_mask
</td>
<td>
matches strings as done by the shell on the command
lines (see "man 7 glob")
</td>
</tr>
<tr>
<td>
class libdar::regular_mask
</td>
<td>
matches regular expressions (see "man 7 regex")
</td>
</tr>
<tr>
<td>
class libdar::not_mask
</td>
<td>
negation of another mask (the mask given
at construction time)
</td>
</tr>
<tr>
<td>
class libdar::et_mask
</td>
<td>makes an *AND* operator between
two or more masks
</td>
</tr>
<tr>
<td>
class libdar::ou_mask
</td>
<td>
makes the *OR* operator between two or more masks
</td>
</tr>
<tr>
<td>
class lbdar::simple_path_mask
</td>
<td>
matches whether the string to evaluate
is subdirectory of, or is the directory itself
that has been given at construction time.
</td>
</tr>
<tr>
<td>
class libdar::same_path_mask
</td>
<td>
matches if the string is exactly the
given mask (no wild card expression)
</td>
</tr>
<tr>
<td>
class libdar::exclude_dir_mask
</td>
<td>
matches if string is the given
string or a sub directory of it
</td>
</tr>
<tr>
<td>class libdar::mask_list
</td>
<td>
matches a list of files defined in a given file
</td>
</tr>
</table>
</div>
<p>
Let's play with some masks:
</p>
<code class=block>
// all files will be elected by this mask
libdar::bool_mask m1(true);
// all string that match the glob expression "A*~" will match.
// the second argument of the constructor tell whether the match is case sensitive so here,
// any file beginning by 'A' or by 'a' and ending by '~' will be selected by this mask:
libdar::simple_mask m2(std::string("A*~"), false);
// m3 is the negation if m2. This mask will thus match
// any string that does not begin by 'A' or 'a' or does not finishing by '~'
libdar::not_mask m3(m2);
// this mask matches any string that is a subdirectory of "/home/joe"
// and any directory that contains /home/joe, meaning
// "/", "/home", "/jome/joe" and any subdirectory are matched.
// here, the second argument is also case sensitivity (so
// "/HoMe" will not be selected by this mask as we set it to "true".
libdar::simple_path_mask m4 = simple_path_mask("/home/joe",
true);
// now let's do some more complex things:
// m5 will now match only strings that are selected by both m2 AND m4
libdar::et_mask m5;
m5.add_mask(m2);
m5.add_mask(m4);
// we can make more interesting things like this, where m5 will select files
// that match m2 AND m4 AND m3. But as <i>m3 is not(m2)</i>, m5 will never
// match any file... but the idea here is to see the flexibility of use:
m5.add_mask(m3);
// but we could do the same with an "ou_mask" and would get a silly
// counterpart of m1 (a mask that matches any files)
libdar::ou_mask m6;
m6.add_mask(m2);
m6.add_mask(m4);
m6.add_mask(m3);
// lastly, the NOT, AND and OR operation can be used recursively.
// Frankly, it's even possible to have masks referring each other!
libdar::not_mask m7(m6);
m6.add_mask(m7);
// now that's to you to build something that makes sense...
</code>
<p>
The idea here is not to create object manually, but to link their
creation to the action and choices the user makes from the user
interface (Graphical User Interface of your application, for example)
</p>
<p>
Now that you've seen the power of these masks, you should know that in
libdar masks are used at several places:
</p>
<ul>
<li>
<p>
A first place is to select files against their
names (without path information) this the argument of the <b>set_selection()</b>
method of <code>libdar::archive_options_*</code> classes.
The mask here does not apply to directories.
</p>
</li>
<li>
<p>
A second place is to select files against their
path+name and it applies here to all type of files including
directories, this is the argument of the <b>set_subtree()</b>
method of <code>libdar::archive_options_*</code> classes.
So with it, you can prune directories, or in any other way restrict the
operation to a particular subdirectory, as well as to a particular
plain file for example.
</p>
<p>
<b>Important note:</b> about this second mask, what
your own mask will be compared to by libdar is the <b>absolute path</b> of
the file under consideration. If you want to exclude <i>/usr/local/bin</i>
from the operation whatever is the <code>fs_root</code>
value (which correspond the -R option of dar) using here a
<code>libdar::simple_mask("/usr/local/bin")</code>
as argument of <code>libdar::archive_options_*::get_subtree()</code>
will do the trick.
</p>
</li>
</ul>
<p>
An exception is the archive testing operation, which has no
<code>fs_root</code> argument (because the operation is not
relative to an existing filesystem), however the
<code>subtree</code> argument exist to receive a mask for
comparing the path of file to include or exclude from the
testing operation. In this case the situation is as if the
<code>fs_root</code> was set to the value "<b><ROOT></b>".
For example, masks will be compared to <code>"<ROOT>/some/file"</code>
when performing an archive test operation.
</p>
<p>
Instead of using explicit string "<ROOT>" you can use
<b>libdar::PSEUDO_ROOT</b> predifined std::string variable
</p>
<ul>
<li>
A third place concerns
Extended Attributes (EA), this is the argument of the
<b>set_ea_mask()</b>method of <code>libdar::archive_options_*</code> classes.
It is applied to the full EA name in the form
<i><domain>.<name></i> where <i><domain></i>
is any string value like but not limited to the usual "user"
or "system" domains.
</li>
<li>
A fourth place concerns the file to compress or to avoid
compressing. This is the argument of the <b>set_compr_mask()</b>
method of <code>libdar::archive_options_*</code>
classes. it is works the same as
<code>set_selection()</code> methods seen above,
based only to filename without any path
consideration.
</li>
<li>
A fifth place concerns files that need to be prepared for
backup, this is the argument of the <b>set_backup_hook()</b>
methods of <code>libdar::archive_option_create</code>
class. I has to be used the same as
<i>set_subtree()</i>. For more about this feature see
the backup-hook feature in dar man page (-<, -> and -= options).
</li>
</ul>
<h2>Aborting an Operation</h2>
<p>
If the POSIX thread support is available,
<i>libdar</i> will be built in a
thread-safe manner, giving you the possibility to have several threads using libdar
at the same time (but on different objects except concerning the
libdar::statistics which can be shared between threads). You may then
wish to interrupt a given thread. But
aborting a thread form the outside (like sending it a KILL signal) will
most of the time let some memory allocated or even worse can lead to
dead-lock situation, when the killed thread was inside a critical section
and had not got the opportunity to release a <u>mutex</u>.
For that reason, libdar proposes a set
of calls to abort any processing libdar call which is ran by a given
thread.
</p>
<code class=block>
// next is the thread ID in which we want to have lidbar call canceled
// here for simplicity we don't describe the way the ID has been obtained
// but it could be for example the result of a call to pthread_self() as
// defined in <pthread.h> system header file
pthread_t thread_id = 161720;
// the most simple call is:
<b>libdar::cancel_thread(thread_id);</b>
// this will make any libdar call in this thread be canceled immediately
// but you can use something a bit more interesting:
<b>libdar::cancel_thread(thread_id, false);</b>
// this second argument is true for immediate cancellation and can be ommited in
// that case. But using false instead leads to a delayed cancellation,
// in which case libdar aborts the operation
// but produces something usable, espetially if you were performing a backup.
// You then get a real usable archive which only contains files saved so far, in place
// of having a broken archive which misses a catalogue at the end. Note that this
// delayed cancellation needs a bit more time to complete, depending on the
// size of the archive under process.
</code>
<p>
As seen above, cancellation can be very simple. What now succeeds when
you ask for a cancellation? Well, an exception of type <code>Ethread_cancel</code>
is thrown. All along his path, memory is released and mutex are freed.
Last, the exception appears to the libdar caller. So, you can catch it
to define a specific comportment. And if you don't want to use
exceptions a special returned code is used.
</p>
<code class=block>
try
{
libdar::archive my_arch(...);
...
}
catch(libdar::Ethread_cancel & e)
{
... do something specific when thread has been canceled;<br>
}
</code>
<p>
Some helper routines are available to
know the cancellation status for a particular thread or to abort a
cancellation process if it has not yet been engaged.
</p>
<code class=block>
thread_t tid;
// how to know if the thread <i>tid</i> is under cancellation process?
if(<b>libdar::cancel_status(tid)</b>)
std::cout << "thread cancellation is under progress for thread : "
<< tid << std::endl;
else
std::cout << "no thread cancellation is under progress for thread : "
<< std::endl;
// how to cancel a pending thread cancellation ?
if(<b>libdar::cancel_clear(tid)</b>)
std::cout << "pending thread cancellation has been reset, thread "
<< tid << " has not been canceled"
<< std::endl;
else
std::cout << "too late, could not avoid thread cancellation for thread "
<< tid
<< std::endl;
</code>
<p>
Last point, back to the <code>libdar::Ethread_cancel</code>
exception, this class has two methods you may find useful, when you
catch it:
</p>
<code class=block>
try
{
... some libdar calls
}
catch(libdar::Ethread_cancel & <b>e</b>)
{
if(e.<b>immediate_cancel</b>())
std::cout << "cancel_thread() has been called with \"true\" as second argument"
<< std::endl;
else
std::cout << "cancel_thread() has been called with \"false\" as second argument"
<< std::endl;
U64 flag = e.<b>get_flag()</b>;
... do something with the flag variable...
}
// what is this flag stored in this exception?<br>
// You must consider that the complete definition of cancel_thread() is the following:
// <i>void cancel_thread</i>(pthread_t tid, bool immediate = true, U_64 flag = 0);
// thus, any argument given in third is passed to the thrown Ethread_cancel exception,
// value which can be retrieved thanks to its get_flag() method. The value given to this
// flag is not used by libdar itself, it is a facility for user program to have the possibility
// to include additional information about the thread cancellation.
// supposing the thread cancellation has been invoked by:
<b>libdar::cancel_thread(thread_id, true, 19);</b>
// then the <i>flag</i> variable in the catch() statement above would have received
// the value <i>19</i>.
</code>
<h2>Dar_manager API</h2>
<p>
For more about <i>dar_manager</i>, please read the man page where are described in
detail its available features.
</p>
<p>
To get dar_manager features you need to use the
<b>class database</b>. Most of the methods of the <i>database</i>
class make use options. The same as what has been seen with class <i>archive</i>
a auxiliary class is used to carry these options.
</p>
<h3>Database object construction</h3>
<p>
Two constructor are available. The first creates a brand-new but empty database in memory:
</p>
<code class=block>
database(const std::shared_ptr<user_interaction> & dialog);
</code>
<p>
As seen for <code>libdar::archive</code> <b>dialog</b> can be set to a null pointer if the
default interaction mode (stdin/stdout/stderr) suits your need.
</p>
<p>
The second constructor opens an existing database from filesystem and
stores its contents into memory ready for further use and actions:
</p>
<code class=block>
database(const std::shared_ptr<user_interaction> & dialog,
const std::string & base,
const <b>database_open_options</b> & opt);
</code>
<p>
<ul>
<li><b>dialog</b> can be set to a null pointer or can point to an user_interaction object of your own</li>
<li><b>base</b> is the path and filename of the database to read</li>
<li>
<b>opt</b> is an object containing a few options. As seen with
<code>libdar::archive</code> we can use an default temporary object to use default
option
</li>
</ul>
Here follows simple examples of use of class <code>database</code>:
</p>
<code class=block>
std::shared_ptr<libdar::user_interaction> ui_ptr; // points to null
<b>libdar::database</b> base(ui_ptr);
// we have created an empty database (no archive in it) called "base"
libdar::database other(ui_ptr, // we can reuse it as it points to nullptr
"/tmp/existing_base.dmd",
libdar::database_open_options());
// we have created a database object called "other" which contains
// (in RAM) all information that were contained in the
// database file "/tmp/existing_base.dmd"
<b>libdar::database_open_option</b> opt;
opt.set_partial(true);
opt.set_warn_order(false);
<b>libdar::database</b> other2(ui_ptr,
"/tmp/existing_base.dmd",
opt);
// we have created yet another database object called "other2" which differs
// from "other" by the option we used. While "other" is a fully loaded
// database, "other2" is a partial database. This notion is explained
// below
</code>
<br/>
<ul>
<li>
<b>database_open_options::set_partial(bool value)</b>
leads dar to only load the database header into memory, which is
quicker than loading the full database. But some operation we will see
bellow need fully loaded database, the other can work with both
</li>
<li>
<b>database_open_options::set_partial_read_only(bool value)</b>
in addition to have only the header the archive is open in read-only
mode which of course forbids any modification to the database but is
even faster than just a partial read-write database. For just database
listing this is perfectly adapted.
</li>
<li>
<b>database_open_options::set_warn_order(bool value)</b> avoid
warning about ordering problem between archive
</li>
</ul>
<p>
In the following we will indicate whether a database operation can be
applied to a partially loaded database or not. All operation can be
applied to a fully loaded databse.
</p>
<h3>Database's methods</h3>
<p>
A database can be open in <b>read-write</b> mode <b>partially loaded (still read-write)</b> mode
and last in <b>partially loaded read-only mode</b>. All operations are available
in the first mode, but some are not in the second and even less in the third mode. We will
detail which one are available in each mode:
</p>
<h4>Available in partially loaded read-only mode</h4>
<ul>
<li><b>show_contents()</b> : list the archives used to build the database</li>
<li>
<b>get_options()</b> : list the options that will be passed to dar (as
defined with the set_options() method)
</li>
<li>
<b>get_dar_path()</b> : return the path to dar (or empty string if
relying on the PATH variable)
</li>
</ul>
<h4>Availabler in partially loaded read-write mode</h4>
<ul>
<li><b>all methods seen above</b></li>
<li>
<b>dump(...)</b> : it is used to write back the database to a file.
</li>
<li>
<b>change_name()</b> : change the basename of the archive which
index is given in argument
</li>
<li>
<b>set_path()</b> : change the path to the archive which index is
given in argument
</li>
<li>
<b>set_options()</b>: change the default options to always pass
to dar when performing restoration
</li>
<li>
<b>set_dar_path()</b> : specify the path to dar (use empty string
to rely on the PATH variable)
</li>
</ul>
<h4>Available in fully loaded read-write mode</h4>
<ul>
<li>
<b>all methods seen above</b>
</li>
<li>
<b>add_archive()</b> : add an archive to the database
</li>
<li>
<b>remove_archive()</b> : remove an archive from the
database
</li>
<li>
<b>set_permutation()</b> : change archive relative order within
the database
</li>
<li>
<b>show_files()</b> : list the files which are present in the
given archive
</li>
<li>
<b>show_version()</b> : list the archive where the given file is
saved
</li>
<li>
<b>show_most_recent_stats()</b> : compute statistics about
the location of most recent file versions
</li>
<li>
<b>restore()</b> : restore a set of given files given in argument.
</li>
</ul>
<p>
Well, you might now say that as description this is a bit light for a
tutorial, yes. In fact these call are really very simple to use, you
can find a complete description in the API reference documentation.
This documentation is built if doxygen is available and is put
under doc/html after calling make in the source
package. It is also available from
<a href="http://dar.linux.free.fr/html/">dar's homepage</a>.
</p>
<h2>Dar_slave API</h2>
<p>
<i>dar_slave</i> role is to read an archive while interacting with
a dar process through a pair of pipes. Dar asks portion of the
archive or information about the archive in the first pipe from
dar to dar_slave. And dar_slave sends the requested information
into the other pipe toward dar (embedded into an expected format).
</p>
<p>
Since API 6.0.x, dar_slave has an API. It is implemented by the class
libdar::libdar_slave. You need firs to create an object using the
following constructor:
</p>
<code class=block>
libdar_slave(std::shared_ptr<user_interaction> & dialog,
const std::string & folder,
const std::string & basename,
const std::string & extension,
bool input_pipe_is_fd,
const std::string & input_pipe,
bool output_pipe_is_fd,
const std::string & output_pipe,
const std::string & execute,
const infinint & min_digits);
</code>
<br/>
<ul>
<li><b>dialog</b> as seen for other libdar classes can be set to a null pointer for interaction on stdin and stdout</li>
<li><b>folder</b> is the directory where resides the archive to read</li>
<li><b>basename</b> is the basename of the archive</li>
<li><b>extension</b> should always be set to "dar"</li>
<li>
<b>input_pipe_is_fd</b> if set to true, the next argument is not the path to a named pipe but a
number corresponding to a file descriptor open open in read mode
</li>
<li><b>input_pipe</b> is the path of a named pipe to read from. It can also be an empty string to use stdin as input pipe</li>
<li
><b>out_pipe_is_fd</b> if set to true, the next argument is not the path to a named pipe but a
number corresponding to a file descriptor open in write mode
</li>
<li><b>output_pipe </b>is the path of a named pipe to write from. It can also be an empty string to use stdout as input pipe</li>
</ul>
<p>
Once the object is created, you will need to call the
<b>libdar_slave::run()</b> method which will end when the
dar process at the other end will no more need of this slave:
</p>
<code class=block>
libdar::libdar_slave slave(nullptr,
"/tmp",
"first_backup",
"dar",
false,
"/tmp/toslave", // assuming this is an existing named pipe
false,
"/tmp/todar", // assuming this is also an existing named pipe
"echo 'reading slice %p/%b.%N.%e in context %c'",
0);
<b>slave.run();</b>
// once run() has returned, you can launch it again for another process
// it will continue to provide access to the /tmp/first_backup.*.dar archive
</code>
<h2>Dar_xform API</h2>
<p>
<i>dar_xform</i>
creates a copy of a given archive modifying its slicing. it does not
require decompressing nor deciphering the archive to do so. There is
different constructor depending whether the archive is read from
filesystem, from a named pipe of from a provided file descriptor
</p>
<h3>Reading from a file</h3>
<code class=block>
libdar::libdar_xform(const std::shared_ptr<user_interaction> & ui,
const std::string & chem,
const std::string & basename,
const std::string & extension,
const infinint & min_digits,
const std::string & execute);
</code>
<br/>
<ul>
<li>
<b>ui</b> as seen so far it can be set to a null pointer for interaction on stdin and stdout
</li>
<li><b>chem</b> is the directory where resides the archive to read</li>
<li><b>basename</b> is the basename of the archive</li><li><b>extension</b> should always be set to "dar"</li>
<li>
<b>min_digits</b> is the minimum number of digits slice number in filename
have been created with (use zero if you don't know what it is)
</li>
</ul>
<h3>Reading from a named pipe</h3>
<code class=block>
libdar_xform(const std::shared_ptr<user_interaction> & dialog,
const std::string & pipename);
</code>
<br/>
<ul>
<li><b>dialog</b> as seen for other libdar classes, it can be set to nullptr</li>
<li><b>pipename</b> complete path to the named pipe to read the archive from</li>
</ul>
<h3>Reading from a file descriptor</h3>
<code class=block>
libdar_xform(const std::shared_ptr<user_interaction> & dialog,
int filedescriptor);
</code>
<br/>
<ul>
<li><b>dialog</b> same as above</li>
<li><b>filedescriptor</b> is an read opened file descriptor to read the archive from</li>
</ul>
<h3>Creating a single or multi-sliced archive on filesystem</h3>
<p>
Once the <code>libdar::libdar_xform</code> object is created it can copy the
referred archive to another location in another form thanks to one of
the two <code>libdar_xform::xform_to</code> methods. There is <u>not link</u> between
the <b>constructor</b> used and the <b>libdar_xform::xform_to</b> flavor used,
any combination is possible.
</p>
<code class=block>
void xform_to(const std::string & path,
const std::string & basename,
const std::string & extension,
bool allow_over,
bool warn_over,
const infinint & pause,
const infinint & first_slice_size,
const infinint & slice_size,
const std::string & slice_perm,
const std::string & slice_user,
const std::string & slice_group,
libdar::hash_algo hash,
const libdar::infinint & min_digits,
const std::string & execute);
</code>
<h3>Creating a single sliced archive toward a filedescriptor</h3>
<code class=block>
void xform_to(int filedescriptor,
const std::string & execute);
</code>
<p>
Here follows an example of use. We will convert a possibly multi-sliced
archive to a single slice one, generating a sha512 hash file on-fly.
</p>
<code class=block>
std::shared_ptr<libdar::user_interaction> ui_ptr; // points to null
libdar::libdar_xform transform(ui_ptr,
"/tmp",
"my_first_archive",
"dar",
0,
"echo 'reading slice %p/%b.%N.%e context is %c'");
transform.xform_to("/tmp",
"my_other_first_archive",
"dar",
false, // no overwriting allowed
true, // does not matter whether we warn or not as we do not allow overwriting
0, // no pause between slices
0, // no specific first slice
0, // no slicing at all (previous argument is thus not used anyway in that case)
"", // using default permission for created slices
"", // using default user ownership for created slices
"", // using default group ownership for created slices
libdar::hash_algo::sha512, // the hash algo to use (for no hashing use hash_none instead)
0, // min_digits ... not using this feature here where from we use "0"
"echo 'Slice %p/%b.%N.%e has been written. Context is %c'");
</code>
<h2>Compilation & Linking</h2>
<h3>Compilation</h3>
<p>
All the symbols found in the libdar API
defined from <b><dar/libdar.h></b>.
So you should only need to include this header.
If the header file is not located in a standard directory,
in order to compile your code, you may need some extra
flags to pass to the compiler (like -I/opt/...).
The <b>pkg-config</b> tool can help here to
avoid system dependent invocation:
</p>
<code class=block>
<i> shell prompt ></i> <b>cat my_prog.cpp</b>
#include <dar/libdar.h>
main()
{
libdar::get_version(...);
...
}
<i> shell prompt ></i> <b>gcc <e>`pkg-config --cflags libdar`</e> -c my_prog.cpp</b>
</code>
<h3>Linking</h3>
<p>
Of course, you need to link your program with libdar. This is done by
adding <b>-ldar</b> plus other library libdar can rely on like libz,
libbzip2, liblzo or libgcrypt, depending on the feature activated at
compilation time. Here too, <b>pkg-config</b> can provide a
great help to avoid having system dependent invocation:
</p>
<code class=block>
<i>shell prompt ></i> <b>gcc <e>pkg-confg --libs libdar`</e> my_prog.o -o my_prog</b>
</code>
<h3>Libdar's different flavors</h3>
<p>
The compilation and linking
steps described above assume you
have a "<b>full</b>" libdar library.
but beside the <i>full</i> (alias <i>infinint</i>)
libdar flavor, libdar also comes in <b>32</B> and <b>64</b> bits
versions. In these last ones, in place of internally relying on a
special type (which is a C++ class called<i> infinint</i>)
to handle arbitrary large integers, <b>libdar32</b> relies on 32 bits integers
and <b>libdar64</b> relies on 64 bits integers (there are limitations which are
described in doc/LIMITATIONS). But all these libdar version (infinint,
32bits, 64bits) have the same interface and must be used the same way,
except for compilation and linking:
</p>
<p>
These different libdar versions can
coexist on the same system, they
share the same include files. But the <b>LIBDAR_MODE</b> macro must be set to
32 or 64 when compiling or linking with libdar32 or libdar64
respectively, this macro changes the way the libdar headers
files are interpreted by the compiler.
<b>pkg-config --cflags</b> will set the
correct LIBDAR_MODE, so you should only bother calling it with either
libdar, libdar32 or libdar64 depending on your need:
<code>"<b>pkg-confg --cflags libdar<e>64</e></b>"</code> for example.
</p>
<code class=block>
<i>shell prompt ></i> <b>cat my_prog.cpp</b>
#include <dar/libdar.h>
main()
{
libdar::get_version(...);
...
}
<i>shell prompt ></i> <b>gcc -c `pkg-config --cflags libdar<e>64</e>` my_prog.cpp</b>
<i>shell prompt ></i> <b>gcc `pkg-config --libs libdar<e>64</e>` my_prog.o -o my_prog</b>>
</code>
<p>
and replace 64 by 32 to link with libdar32.
</p>
</body>
</html>
|