# LIBDAR

# APPLICATION INTERFACE

# TUTORIAL

for API version 3.0.x

## Presentation

Libdar is a library that has been built from source code initially located in dar command line application. The features that libdar provides are the ability to handle Disk ARchive (dar)'s archives, thanks to the following operations:

- archive creation,
- file extraction,
- archive listing,
- archive testing,
- archive comparison,
- catalogue isolation.

Note that Disk ARchive has been released under the Gnu General Public License (GPL), and so is the code of libdar. So, to link your code with libdar (statically or dynamically), your application must also be covered by the GPL.
This tutorial will show you how to use libdar from the API. As the dar command line now also uses this API, looking at his code may also be interesting as illustration, in particular the file dar_suite/dar.cpp.
The sample codes provided here are very simple code that could let you see overall process of using libdar, they may or may not compile, I have even not tried to, so just use them as illustration, no more. Note that there is a documentation reference for this API which is built with dar under the directory doc/html if you have Doxygen available and can be consulted on the web.

## Let's Start

### conventions

#### Language

Dar and libdar are written in C++, and so is the libdar API. Libdar is thus easily usable with C or C++ code. For other languages, it depends on so many things (calling convention, etc.) that I would just say you are welcome to provide the necessary adaptation layer for any particular language. :-)

#### Libdar namespace

All libdar symbols are defined under the libdar namespace. You can either add the using namespace libdar; line at the beginning of your source files:

`using namespace libdar;` `get_version(....);`

or, as we will do in the following examples, you can explicitely use the namespace in front of libdar objects :
``

`libdar::get_version(....);`

#### Exceptions or not Exceptions

For each point we will see two ways of using libdar. One, is using exception, the other is without exceptions. They will be displayed this way :

`example code using exceptions` | `example code not using exceptions`

All exceptions used by libdar inherit from the pure virtual class Egeneric. The only method you will need to know about for any exception is the get_message() call, which returns a string explaining the reason of the message in a human language. The type of the error is defined by the class of the exception. Here follows all the exception classes and their meaning:

`class libdar::Egeneric` | this is the parent class of all exception classes (a pure virtual class)
`class libdar::Ememory` | exception used when memory has been exhausted
`class libdar::Ebug` | exception used to signal a bug. A bug is triggered when reaching some code that should never be reached
`class libdar::Einfinint` | exception used when arithmetic error is detected when operating on infinint
`class libdar::Elimitint` | exception used when a limitint overflow is detected, the maximum value of the limitint has been exceeded
`class libdar::Erange` | exception used to signal range error
`class libdar::Edeci` | exception used to signal convertion problem between infinint and string (decimal representation)
`class libdar::Efeature` | exception used when a requested feature is not (yet) implemented
`class libdar::Ehardware` | exception used when hardware problem is found
`class libdar::Euser_abort` | exception used to signal that the user has aborted the operation
`class libdar::Edata` | exception used when an error concerning the treated data has been met
`class libdar::Escript` | exception used when the inter-slice user command returned an error code
`class libdar::Elibcall` | exception used to signal an error in the arguments given to a libdar call of the API
`class libdar::Ecompilation` | exception used when a requested fearture has not beed activated at compilation time

## 1 - First we *must* check the libdar version

`
// we include this to be able to display some
// messages
#include <io.h>
// we include this header to access lidbar API
#include <dar/libdar.h>
// all sample code shown will be inside this
// function for simplicity of the examples
void my_sample_function()
{
try
{
libdar::U_I maj, med, min;
// first we MUST call get_version()
libdar::get_version(maj, med, min);
if(maj != libdar::LIBDAR_COMPILE_TIME_MAJOR ||
med < libdar::LIBDAR_COMPILE_TIME_MEDIUM)
throw libdar::Erange("initialization",
"we are linking against a wrong libdar");
}`
`catch(libdar::Egeneric & e)
{
std::cout << e.get_message() << std::endl;
}
}
`

``
`// we include this to be able to display some
// messages
#include <io.h>
// we include this header to access lidbar API
#include <dar/libdar.h>
// all sample code shown will be inside this
// function for simplicity of the examples
void my_sample_function()
{
` `libdar::U_I maj, med, min;
libdar::U_16 excode;
std::string msg;
` `
// first we MUST call get_version()
libdar::get_version_noexcept(maj, med, min,
excode, msg);
if(excode != LIBDAR_NOEXCEPT)
{
std::cout << msg << endl;
return;
}
if(maj != LIBDAR_COMPILE_TIME_MAJOR ||
` `med < libdar::LIBDAR_COMPILE_TIME_MEDIUM``)
{
std::cout <<` `"we are linking against wrong libdar"``<< std::endl;
return;
}
`

<dar>The get_version* family function must be called for several reasons :
</dar>

- you must check that the library you dynamically link with is compatible with the features you will use. The major number must be the same as no compatibility is assured between two libdar versions of different major number. And, the medium number must be greater or equal to the one used at compilation time to be sure that all the feature you have been using are available in the libdar library you dynamically link with. Changes between minor versions correspond to bug fixes which does not implies any API change, so there is no constraint about minor number.
- the get_version* calls, over returning version information, makes important initialization tasks for libdar. If it is not called first, the libdar library is not initialized and its behavior is unpredictable. Note that you may call get_version* several time if you wish, and in any flavor.

## 2 - Let's see the compilation time features

once we have called a function of the get_version* family it is possible to access the features activated at compilation time:

`
void my_sample_function()
{
// let's continue in the same function
bool ea;
bool largefile;
bool nodump;
bool special_alloc;
libdar::U_I bits;
bool thread_safe;
bool libz;
bool libbz2;
bool libcrypto;
libdar::get_compile_time_features(ea,
largefile,
nodump,
special_alloc,
bits,
thread_safe,
libz,
libbz2,
libcrypto);
`
}

`` `
// here there is no difference because no exceptions
// are thrown by the get_compile_time_feature()
// function
`

You can do what you want with the resulting values, like displaying the libdar available feature, or even filter if you don't want to continue when a particular feature is missing. But, that's maybe not necessary to worry here, because libdar will tell you if the operation you ask requires a feature that has not been activated at compilation time thanks to the Ecompile exception or the LIBDAR_ECOMPILATION error code.

## 3 -User interaction

### The generic user_interaction class

To be able to report messages to the user and to be able to ask questions to the user, a special class called user_interaction has been introduced as first argument of the API calls we will see below. Rawly, user_interaction is a pure virtual class from which you can define your own inherited class to have your very own implementation of the interaction with the user (GUI's graphical interaction, for example). You will just have to override four methods which prototypes follow :
void pause (const std::string &message);
this method is called by libdar to request an boolean answer from the user. The question is given in argument and the pause() method must either return if the user agreed the question (said "yes" or "true"), or throw a Euser_abort exception if the user refused the proposition. Don't worry about thowing exception in your code, it will be trapped by libdar if you don't want to manage exceptions, and use libdar in the "no exception" manner.
void warning (const std::string &message);
libdar call this method to display an informational message to the user. It may not always be a warning as the name suggests, sometimes it is just normal information.
std::string get_string (const std::string &message, bool echo);
This call is used to get a arbitrary answer from the user. As this is actually mainly used to get a password from the user (when no password has been suplied for an encrypted archive), the echo argument tells that the user answer shall or shall not be displayed on screen. If echo is set to "false" the implementation of get_string() must hide the character typed by the user in answer to the displayed question.
user_interaction * clone () const;
This is a technical call that must return a copy of the "this" object, like would do the copy constructor. Why not simply use the copy constructor? because libdar may need to keep an internal copy of the object. But the object which class is an inherited class of user_interaction is not know by his real class but through a user_interaction pointer type. So invoking the copy constructor of the user_interaction class will make the new object copied only for the user_interaction part, this may cause a crash when using the object copy. A simple implementation of this method should be something like this (even if you don't want to use exceptions):
````

`` `user_interaction *my_own_class::clone() const { my_own_class *ret = new my_own_class(*this); if(ret == NULL) throw Ememory("user_interaction_callback::clone"); else return ret; }`

### The callback interaction class

A inherited class from user_interaction called user_interaction_callback proposes an implementation of the user interaction based on callback functions. This just replaces the three interactions methods (pause, warning and get_string) by three normal functions of your choice, which must be given to the user_interaction_callback's constructor and you don't have to consider the clone() method. But you still need to implement theses callback functions. For a real example, I propose you to have a look at what is done for dar's command line. dar's user interaction is done thanks to an object of the user_interaction_callback class and three static functions of the module dar_suite/shell_interaction.cpp
Just a note however about the contextual value present in the arguments of theses callback functions :
````

`` `
// our own callback functions.
// for the illustration of what theses 'context' arguments
// can be used for we will imagine the situation where
// multiple windows or multiple threads may each one use
// libdar. But all share the same callback functions
typedef class t_window_type t_win;
// this is an arbitrary type that here we will say
// points to a graphical window object wrapped in a C++
// class.
// Note that the show() wait_for_click() and so one
// methods attributed to the t_win class are absolutely
// imaginary. Any link to an existing class is a pure
// coincidence...
void warning_callback(const std::string &x, void *context)
{
(t_win *)(context)->show(x);
}
bool answer_callback(const std::string &x, void *context)
{
click_type ret;
` `(t_win *)(context)->show(x);
ret = (t_win *)(context)->wait_for_click();
return ret == click_OK;
` `}
std::string string_callback(const std::string &x, bool echo, void *context)
{
(t_win *)(context)->show(x);
if(!echo)
(t_win *)(context)->set_hide_typed_char();
(t_win *)(context)->wait_for_click();
return (t_win *)(context)->read_text();
}
---------8<-------8<-------8<-------
// So now each window can have it user_interaction object based on the same
libdar::user_interaction_callback dialog =
libdar::user_interaction_callback(&warning_callback, &answer_callback, &string_callback,
(void *)get_current_windows_id());
// just the "context" argument changes, and will be passed asis from the constructor to the callback
// functions
`

## 4 - Masks

Mask are used to define which file are to be considered and which are not to be considered. Libdar implements masks as several classes that all inherit from a pure virtual class that defines the way masks are used. This root class is the class mask and provides the is_covered() method for libdar to know which files to consider. Here follows the different basic masks classes you can use to build very complex masks:

class libdar::mask | the generic class, parent of all masks (a pure virtual class)
class libdar::bool_mask | boolean mask, either always true or false, it matches either all files or no files at all
class libdar::simple_mask | matches as done by the shell on the command lines (see "man 7 glob")
class libdar::regular_mask | matches regular expressions (see "man 7 regex")
class libdar::not_mask | negation of another mask
class libdar::et_mask | makes an *AND* operator between two or more masks
class libdar::ou_mask | makes the *OR* operator between two or more masks
class lbdar::simple_path_mask | string matches if it is subdir of mask or mask is a subdir of expression
class libdar::same_path_mask | matches if the string is exactly the given mask (no wilde card expression)
class libdar::exclude_dir_mask | matches if string is the given string or a sub directory of it

Let's play with some masks :
````

`
` `// all files will be elected by this mask`
`libdar::bool_mask m1 = true;
// all file that match the glob expession "A*~" will match.
// the second argument of the constructor tell if the match is case sensitive so here
// any file beginning by 'A' or by 'a' and ending by '~' will be elected by this mask
libdar::simple_mask m2 = libdar::simple_mask(std::string("A*~"), false);
// m3 is the negation if m2. This mask will thus match
// any file that does not begin by 'A' or 'a' and also finish by '~'
libdar::not_mask m3 = m2;
// this mask matches any file that is a subdirectory of "/home/joe"
// and any file that has /home/joe as subdirectory, that is:
// "/", "/home", "/jome/joe" and any subdirectory are matched.
// the second argument here too is the case sensitivity (so here
// "/HoMe" will not be elected by this mask.
libdar::simple_path_mask m4 = simple_path_mask("/home/joe", true);
// now let's do some more complex things:
` `// m5 will now match only files that are elected by both m2 AND m4`
`libdar::et_mask m5;
m5.add_mask(m2);
m5.add_mask(m4);
// we can make more silly things like this, where m5 will select files
// that match m2 AND m4 AND m3. But m3 = not m2 so now m5 will never
// match any file...
m5.add_mask(m3);
// but we could do the same with a "ou_mask" that realizes the OR operation
// and we would get an silly equivalent of m1 (a mask that matches any files)
libdar::ou_mask m6;
m6.add_mask(m2);
m6.add_mask(m4);
m6.add_mask(m3);
// last point, the NOT, AND and OR operation can be used recurively :
` `// even this, is possible where two ask are used as reference for each other !`
`libdar::not_mask m7 = m6;
m6.add_mask(m7);
`

Now that you see a bit more all the power of masks, you must know that in quite all libdar operations two masks are required:

- The first mask is used against filenames, but is not applied to directories, nor it is applied to the path part of the filenames. This first mask may be any combinaison of the masks seen previously, it will only be applied to socket, named pipes, symbolic links, char or block devices, plain files, but not to directories as we said. This way you can filter by type of file you want or don't want to save, restore, list, compaire, compress and so on.
- The second mask is applied to any file including directories and including the path part of the filename. So with it you can prune directories, or in the other way restrict the operation to a particula subdirectory, as well as to a particular plain file for example.

``

## 5 - Let's create a simple archive

Now that we have seen masks and exceptions classes let's start the real thing:

`// creating an archive is simple, it is just
// calling the "create" constructor of the archive
// class. It may be used for full or differential
// archive. But we will see differential later.
// my_arch should have been an object instead of a
// pointer to an archive object.
libdar::user_interaction_callback dialog = libdar::user_interaction_callback(ptr1, ptr2, ptr3);
// where ptr1, ptr2 and ptr3 are three callback
// functions.
libdar::statistics ret;
// we will see this structure a bit further
libdar::archive *my_arch =
new libdar::archive(dialog,
"/home", // saving all under this "root"
"/tmp", // where the slices will go
NULL, // we do a full backup for now
libdar::not_mask(simple_mask("*~", true)),
// we don't save the files ending with
// '~' this does not concern directories
libdar::bool_mask(true),
// all directories and files not rejected
// by the previous mask are saved
"my_archive",
// the basename of the slices
"dar", // dar's slice extensions
true, // we allow slice overwriting
true, // but ask to be warned in such occurence
false, // we don't want a verbose output
false, // nor we want to pause between slices
true, // rejected directory will be saved as
// empty (no directory is rejected so
// here there is no importance for that
// parameter)
libdar::gzip // the archive will be compressed
// using gzip
9, // at maximum compression level
0, // no slicing is done,
0, // so the first slice size must also be
// set to zero
true, // root EA will be saved if present
true, // user EA too
"", // no script will be executed between
// slices (as there is no slicing)
libdar::crypto_blowfish,
// the blowfish strong encryption
// will be used
"", // as the password is not given here
// (empty string is not a valid password)
// it will be asked interactively to the
// user through the dialog
// user_interaction object
20480, // the block of encryption will be
// 20 kbytes
libdar::not_mask(libdar::simple_mask("*gz")),
// all files will be compressed except
// those ending by "gz"
800, // file which size is below 800 bytes
// will not be compressed
false, // all files will be saved whatever is
// the nodump flag value
false, // as we make a full backup this
// "ignore_owner" parameter is useless
0, // hourshift is useless here as we make
// a full backup
false, // we will make a real archive not a
// dry-run operation
true, // dar will set back the access time of
// file it opens, which will change the
// ctime date of theses files
false, // we may change of filesystem if
// necessary
ret); // this value is returned by libdar`

```// creating an archive is simple, it is just
// calling the "create" constructor of the archive
// class. It may be used for full or differential
// archive. But we will see differential later.
// my_arch should have been an object instead of a
// pointer to an archive object.
` `
libdar::user_interaction_callback dialog = libdar::user_interaction_callback(ptr1, ptr2, ptr3);
// where ptr1, ptr2 and ptr3 are three callback
// functions.
libdar::statistics ret;
` `// we will see this structure a bit further
` `U_16 exception,
std::string except_msg;`
`libdar::archive *my_arch =
libdar::create_archive_noexcept(dialog,`
`"/home", // saving all under this "root"
"/tmp", // where the slices will go
NULL, // we do a full backup for now
libdar::not_mask(simple_mask("*~", true)),
// we don't save the files ending with
// '~' this does not concern directories
libdar::bool_mask(true),
// all directories and files not rejected
// by the previous mask are saved
"my_archive",
// the basename of the slices
"dar", // dar's slice extensions
true, // we allow slice overwriting
true, // but ask to be warned in such occurence
false, // we don't want a verbose output
false, // nor we want to pause between slices
true, // rejected directory will be saved as
// empty (no directory is rejected so
// here there is no importance for that
// parameter)
libdar::gzip // the archive will be compressed
// using gzip
9, // at maximum compression level
0, // no slicing is done,
0, // so the first slice size must also be
// set to zero
true, // root EA will be saved if present
true, // user EA too
"", // no script will be executed between
// slices (as there is no slicing)
libdar::crypto_blowfish,
// the blowfish strong encryption
// will be used
"", // as the password is not given here
// (empty string is not a valid password)
// it will be asked interactively to the
// user through the dialog
// user_interaction object
20480, // the block of encryption will be
// 20 kbytes
libdar::not_mask(libdar::simple_mask("*gz")),
// all files will be compressed except
// those ending by "gz"
800, // file which size is below 800 bytes
// will not be compressed
false, // all files will be saved whatever is
// the nodump flag value
false, // as we make a full backup this
// "ignore_owner" parameter is useless
0, // hourshift is useless here as we make
// a full backup
false, // we will make a real archive not a
// dry-run operation
true, // dar will set back the access time of
// file it opens, which will change the
// ctime date of theses files
false, // we may change of filesystem if
// necessary
ret, // this value is returned by libdar
exception, // thisgives the status of the call
except_msg); // and in case of error the cause.
if(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< std::endl;
`

When creating an archive, the created archive object can be used only as reference for a isolation or for differential backup. You cannot use it for restoration, listing, comparison, because the underlying file descriptors are openned in write only mode. An implementation which uses file descriptors in read-write access is not possible and is not a good idea anyway. Why ? Because, for example, if you want to test your just created archive, using the just created object would make the testing rely on information stored in virtual memory (the archive contents, the data location of a file, etc.), not in the file archive. If some corruption occured in the file you would not notice it.
So to totally complete the archive creation we must destroy the archive object we have just created, which have also as consequence to close any file descriptor used by the object :

`delete my_arch;` | `libdar::close_archive_noexcept(my_arch, exception, except_msg);` `if(exception != LIBDAR_NOEXCEPT) std::cout << "an error occured: " << except_msg << std::endl;`

## 6 - Testing the archive we have created

So, as explained previously, we must create a new archive object but this time with the "read" constructor:
`
`

`
my_arch = new` `libdar::archive(dialog,
"/tmp", // where is the archive
"my_archive", // slice name
"dar", // dar's archive extensions
libdar::crypto_blowfish,
"",
20480, // theses last three are for encryptions
"", // not used as we didn't gave "-" as
"", // slice name
"", // no command executed for now
false); // no verbose output
`

`
my_arch =` `libdar::open_archive_noexcept(``dialog,
"/tmp", // where is the archive
"my_archive", // slice name
"dar", // dar's archive extensions
libdar::crypto_blowfish,
"",
20480, // theses last three are for encryptions
"", // not used as we didn't gave "-" as
"", // slice name
"", // no command executed for now
false, // no verbose output
` `exception,// this gives the status of the call
except_msg); // and in case of error the
// cause of the error
i``f(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< std::endl;`
`
`

Now that we have openned the archive we can perform all operation on it, let's thus start by testing the archive coherence:

`
ret = my_arch->op_test(dialog,
libdar::bool_mask(true),
// all files are tested
libdar::bool_mask(true),
//no directory is prune
false); // no verbose output
`

`
ret = libdar::op_test_noexcept(``dialog,
my_arch, // the archive to test
libdar::bool_mask(true),
// all files are tested
libdar::bool_mask(true),
//no directory is prune
false, // no verbose output`
`exception,// this gives the status of the call
except_msg); // and in case of error the
// cause of the error
` `i``f(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< std::endl;
`

We have tested the archive, but have not yet seen the libdar::statistics variable. It has been used to create an archive as well as here to test it. This structure reports the number of files treated, as well as the number files with error and the type of error. You can have a look at the API reference guide for more information about the use of different field. Here is an example, which relies on the class deci to display the value of an infinint variable:
````

`// we need the class deci to display the value of an infinint:` ```#include "deci.hpp" std::cout << std::string("Number of file treated :") << libdar::deci(ret.treated).human() << std::endl; // or much more simple (but totally equivalent): std::cout << std::string("Number of file treated :") libdar::<< ret.treated << std::endl;`

Note that the use of the class deci may throw exceptions (in case of lack of memory, for example), and there is actually no wrapper available to trap the exceptions that may be thrown by the class deci. So you have to protect the code using a try {} catch {} statment.

## 7 - listing archive contents

The simple way:

`
my_arch->op_listing(dialog,
false, // not a verbose output
false, // not using the tar-like format
bool_mask(true),
// all filenames are listed
false);// do not filter unsaved files
`

`
libdar::op_test_listing(``dialog,
` `false, // not a verbose output
false, // not using the tar-like format
bool_mask(true),
// all filenames are listed
false,// do not filter unsaved files`
`exception,// this gives the status of the call
except_msg); // and in case of error the
// cause of the error
` `i``f(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< endl;
`

The listing will be done calling the warning() method of the dialog object once for each file to list. This may not be very interesting because you will have just a string for each file, and it would require some parsing if you would like to split the listing in column, or display only filenames first and have other information available to the user in another way. The solution to this problem is to change the user_interaction object.
The user_interaction class has a listing() method which provides as much arguments as different information to display:

- filename,
- permission,
- user,
- group,
- file size,
- last modification date,
- if the file is a directory
- if the file has children or is an empty dir
- file type
- flag about saved data / saved EA / compression used

In the user_interaction class (a pure virtual class), the listing() method is not a pure virtual method, so you are not obliged to overwrite it, but it has just an empty implemtation so it does nothing. You understand now that, by default, this method is not used. To activate it, you must call set_use_listing(true) protected method and of course you will have to ovewrite the listing() method to have a less silly behavior:
````

`// here follows the definition of our own implementation of
// of a user_interaction class
class my_user_interaction : public user_interaction
{
public :
// the inherited pure virtual methods we must define
// as seen at the beginning of this tutorial:
void pause(const std::string & message);
` `void warning(const std::string & message);
std::string get_string(const std::string & message, bool echo);
user_interaction *clone() const;
// we can overwrite this method to have splitted fields for listing:
void listing(const std::string & flag,
const std::string & perm,
const std::string & uid,
const std::string & gid,
const std::string & size,
const std::string & date,
const std::string & filename,
bool is_dir,
bool has_children);
// but it will not get used by libdar unless we call the protected method set_use_listing()
// for example this can be done in the class constructor :
my_user_interaction() { set_use_listing(true); };
};
`

Now assuming we have implemented the listing() method in my_user_interaction class, calling op_listing() exactly as we did in the simple way, but just replacing the dialog object by one of the my_user_interaction class, would make this listing() method called for each file to be listed, in place of the warning() method.
As seen at the beginning of this tutorial too, there is a children class of user_interaction based on callback functions which is called user_interaction_callback. The listing() method must also be activated here. This is done automatically when you give a callback function to the object, thanks to the set_listing_callback() method :
````

`` `
// our mandatory callback functions:
void warning_callback(const std::string &x, void *context)
{
....
}
bool answer_callback(const std::string &x, void *context)
{
....
}
std::string string_callback(const std::string &x, bool echo, void *context)
{
....
}
// let's build a user_interaction_callback object:
libdar::user_interaction_callback dialog =
libdar::user_interaction_callback(&warning_callback, &answer_callback, &string_callback, NULL);
// at this point our dialog object is perfectly operational for listing
// but libdar will call the warning_callback function to list the archive
// contents
// a new callback function for listing :
void listing_callback(const std::string & flag,
const std::string & perm,
const std::string & uid,
const std::string & gid,
const std::string & size,
const std::string & date,
const std::string & filename,
bool is_dir,
bool has_children,
void *context)
{
....
}
dialog.set_listing_callback(&listing_callback);
// now libdar will call the listing_callback function when we
// will use this dialog object for listing the archive contents.
`

## 8 - comparing with filesystem

comparison is realized by calling the op_diff method of the class archive.

`
ret = my_arch->op_diff(dialog,
"/home", // what directory to take
// as root we shall
// compare the archive
// contents to
libdar::bool_mask(true),
libdar::bool_mask(true),
false, // no verbose output
true, // comparing root EA
true, // comparing user EA
false, // do not ignore ownership
// differences
false); // do not set back atime
// of read files
`

`
ret =` `libdar::op_diff_noexcept(dialog,
my_arch, // the archive to use
"/home", // what directory to take
// as root we shall
// compare the archive
// contents to
libdar::bool_mask(true),
libdar::bool_mask(true),
false, // no verbose output
true, // comparing root EA
true, // comparing user EA
false, // do not ignore ownership
// differences
false, // do not set back atime
// of read
files` `exception, // this gives the
// status of the call
except_msg); // and in case of
// error the cause of the
// error
` `i``f(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< std::endl;
` ``

simple, no ?

## 9 - restoring files

restoration of files is done by calling the op_extract method of archive class.

`
ret = my_arch->op_extract(dialog,
"/tmp", // where to restore files to
libdar::bool_mask(true),
// restore any filename
libdar::simple_path_mask("denis/.tcshrc",
true),
// but only restore
// this file or directory
false,// overwriting not allowed
true, // warn before overwriting
// useless here, not overwritting
true, // verbose output
true, // remove files marked as deleted
// useless here too, as verwriting
// has been disabled
false,// restore even if a file is more
// recent, (useless here too)
true, // restore root EA
true, // restore user EA
false,// restore directory structure
false,// restore ownership
false,// don't warn if a file to be
// removed has a type that does
// the type of the orginal file
0, // no daylight saving consideration
false); // not a dry-run execution
`

`
ret = libdar::op_extract_noexcept(``dialog,
my_arch, // the archive to test
` `"/tmp", // where to restore files to
libdar::bool_mask(true),
// restore any filename
libdar::simple_path_mask("denis/.tcshrc",
true),
// but only restore
// this file or directory
false,// overwriting not allowed
true, // warn before overwriting
// useless here, not overwritting
true, // verbose output
true, // remove files marked as deleted
// useless here too, as verwriting
// has been disabled
false,// restore even if a file is more
// recent, (useless here too)
true, // restore root EA
true, // restore user EA
false,// restore directory structure
false,// restore ownership
false,// don't warn if a file to be
// removed has a type that does
// the type of the orginal file
0, // no daylight saving consideration
false,// not a dry-run execution`
```exception,// this gives the status of the call
except_msg); // and in case of error the
// cause of the error
` `i``f(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< std::endl;
`

## 10 - isolating the catalogue

OK, I know, catalogue is not an english word (one would rather write catalog), but that's the name of the C++ class used in libdar, so we will keep using it here. Note that you don't have to directly access to this class.
Isolating the catalogue creates a new archive that only contains the list of files and their attributes (ownership, dates, size, etc.), but no data and no EA are stored in it. It is very similar to the same archive one get if he would made a differential backup of a filesystem that has not changed since the archive of reference. The usage is very similar to the archive creation, but it uses a different constructor that has less arguments :

`
libdar::archive *my_cat = new libdar::archive(dialog,
"/tmp", // where is saved the
// extracted catalogue
my_arch, // the archive of reference
// is the one we have been
// playing with previously
"my_catalogue", // slice name
"dar", // file extension
true, // allow slice overwriting
true, // but warn before
true, // verbose output
true, // pause between slices
libdar::bzip2, // compression
9, // max compression level
3000, // cut in slices of 3000 Bytes
3000, // first slice size is the same
"echo slice %p/%b.%n.%e created",
// the script to run after
// slice creation
libdar::crypto_none, // no encryption
"", // unused password
0, // unused crypto size
false); // not a dry-run execution
`

`
libdar::archive *my_cat =
libdar::op_isolate_noexcept(dialog,
` `"/tmp", // where is saved the
// extracted catalogue
my_arch, // the archive of reference
// is the one we have been
// playing with previously
"my_catalogue", // slice name
"dar", // file extension
true, // allow slice overwriting
true, // but warn before
true, // verbose output
true, // pause between slices
libdar::bzip2, // compression
9, // max compression level
3000, // cut in slices of 3000 Bytes
3000, // first slice size is the same
"echo slice %p/%b.%n.%e created",
// the script to run after
// slice creation
libdar::crypto_none, // no encryption
"", // unused password
0, // unused crypto size
false, // not a dry-run execution`
```exception,
// this gives the status
// of the call
except_msg);
// and in case of error the
// cause of the error
` `i``f(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< std::endl;
`

Now we have two archive objects. my_arch is a read-only object created by the "read" constructor. You can do any operations with it, like file restoration, file comparison, archive testing, as we have done in the previous paragraphs. The second archive object is my_cat which is a write only object. It can only be used as reference for another backup (a differential backup) or as a reference for a subsequent catalogue isolation (which would just clone the already isolated catalogue object, here).
Note, that an isolated catalogue can be tested, compared with filesystem, and even you can try to restore files from it. But as there is no data associated with files contents, dar will not restore any file from it, of course. So for now we will just destroy the extracted catalogue object, for all its file descriptors to be closed:

`delete my_cat;` | ```close_archive_noexcept (my_cat, exception, except_msg);` `if(exception != LIBDAR_NOEXCEPT) std::cout << "an error occured: " << except_msg << std::endl;``` ``

and we keep the my_arch object for our last operation :

## 11 - creating a differential backup

This operation is the same as the first one we did (archive creation). You have maybe noted that an argument was set to NULL, here we will give it the value of my_arch which means that my_arch will become the archive of reference for the archive we will create. If we had not destroyed my_cat above, we could have been using it in place of my_arch for exactly the same result.

`
libdar::archive *my_other_arch =
new libdar::archive(dialog,
"/home", // saving all under this "root"
"/tmp", // where the slices will go
my_arch, // differential backup
not_mask(simple_mask("*~", true)),
// we don't save the files ending with
// '~' this does not concern directories
bool_mask(true),
// all directories and files not rejected
// by the previous mask are saved
"my_archive",
// the basename of the slices
"dar", // dar's slice extensions
true, // we allow slice overwriting
true, // but ask to be warned in such occurence
false, // we don't want a verbose output
false, // nor we want to pause between slices
true, // rejected directory will be saved as
// empty (no directory is rejected so
// here there is no importance for that
// parameter)
libdar::gzip // the archive will be compressed
// using gzip
9, // at maximum compression level
0, // no slicing is done,
0, // so the first slice size must also be
// set to zero
true, // root EA will be saved if present
true, // user EA too
"", // no script will be executed between
// slices (as there is no slicing)
libdar::crypto_blowfish,
// the blowfish strong encryption
// will be used
"", // as the password is not given here
// (empty string is not a valid password)
// it will be asked interactively to the
// user through the dialog
// user_interaction object
20480, // the block of encryption will be
// 20 kbytes
not_mask(simple_mask("*gz")),
// all files will be compressed except
// those ending by "gz"
800, // file which size is below 800 bytes
// will not be compressed
false, // all files will be saved whatever is
// the nodump flag value
false, // as we make a full backup this
// "ignore_owner" parameter is useless
0, // hourshift is useless here as we make
// a full backup
false, // we will make a real archive not a
// dry-run operation
true, // dar will set back the access time of
// file it opens, which will change the
// ctime date of theses files
false, // we may change of filesystem if
// necessary
ret); // this value is returned by libdar`

````
`libdar::archive *my_other_arch =
libdar::create_archive_noexcept(dialog,`
`"/home", // saving all under this "root"
"/tmp", // where the slices will go
` `my_arch, // differential backup` `
not_mask(simple_mask("*~", true)),
// we don't save the files ending with
// '~' this does not concern directories
bool_mask(true),
// all directories and files not rejected
// by the previous mask are saved
"my_archive",
// the basename of the slices
"dar", // dar's slice extensions
true, // we allow slice overwriting
true, // but ask to be warned in such occurence
false, // we don't want a verbose output
false, // nor we want to pause between slices
true, // rejected directory will be saved as
// empty (no directory is rejected so
// here there is no importance for that
// parameter)
libdar::gzip // the archive will be compressed
// using gzip
9, // at maximum compression level
0, // no slicing is done,
0, // so the first slice size must also be
// set to zero
true, // root EA will be saved if present
true, // user EA too
"", // no script will be executed between
// slices (as there is no slicing)
libdar::crypto_blowfish,
// the blowfish strong encryption
// will be used
"", // as the password is not given here
// (empty string is not a valid password)
// it will be asked interactively to the
// user through the dialog
// user_interaction object
20480, // the block of encryption will be
// 20 kbytes
not_mask(simple_mask("*gz")),
// all files will be compressed except
// those ending by "gz"
800, // file which size is below 800 bytes
// will not be compressed
false, // all files will be saved whatever is
// the nodump flag value
false, // as we make a full backup this
// "ignore_owner" parameter is useless
0, // hourshift is useless here as we make
// a full backup
false, // we will make a real archive not a
// dry-run operation
true, // dar will set back the access time of
// file it opens, which will change the
// ctime date of theses files
false, // we may change of filesystem if
// necessary
ret, // this value is returned by libdar
exception, // thisgives the status of the call
except_msg); // and in case of error the cause.
if(exception != LIBDAR_NOEXCEPT)
std::cout << "an error occured: " << except_msg
<< std::endl;
`

As previously my_other_arch is a write only object that we won't need anymore. So we destroy it:

`delete my_other_arch;` | `libdar::close_archive_noexcept(my_other_arch, exception, except_msg);` `if(exception != LIBDAR_NOEXCEPT) std::cout << "an error occured: " << except_msg << std::endl;`

So, we are at the end of the tutorial, but still remains an object we need to destroy to cleanly release the memory used :

`delete my_arch;` | `libdar::close_archive_noexcept(my_arch, exception, except_msg);` `if(exception != LIBDAR_NOEXCEPT) std::cout << "an error occured: " << except_msg << std::endl;`

For more detailed information about the API you have the API reference guide, built from source code by Doxygen.

##

<dar></dar>