Disk ARchive  2.4.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/libdar/catalogue.hpp
00001 /*********************************************************************/
00002 // dar - disk archive - a backup/restoration program
00003 // Copyright (C) 2002-2052 Denis Corbin
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 //
00019 // to contact the author : http://dar.linux.free.fr/email.html
00020 /*********************************************************************/
00021 // $Id$
00022 //
00023 /*********************************************************************/
00024 
00028 
00029 #ifndef CATALOGUE_HPP
00030 #define CATALOGUE_HPP
00031 
00032 #include "../my_config.h"
00033 
00034 extern "C"
00035 {
00036 #if HAVE_UNISTD_H
00037 #include <unistd.h>
00038 #endif
00039 } // end extern "C"
00040 
00041 #include <vector>
00042 #include <map>
00043 #include "infinint.hpp"
00044 #include "generic_file.hpp"
00045 #include "path.hpp"
00046 #include "header_version.hpp"
00047 #include "ea.hpp"
00048 #include "compressor.hpp"
00049 #include "integers.hpp"
00050 #include "mask.hpp"
00051 #include "special_alloc.hpp"
00052 #include "user_interaction.hpp"
00053 #include "label.hpp"
00054 #include "escape.hpp"
00055 
00056 namespace libdar
00057 {
00058     class etoile;
00059     class entree;
00060 
00063 
00064     enum saved_status
00065     {
00066         s_saved,      //< inode is saved in the archive
00067         s_fake,       //< inode is not saved in the archive but is in the archive of reference (isolation context) s_fake is no more used in archive format "08" and above: isolated catalogue do keep the data pointers and s_saved stays a valid status in isolated catalogues.
00068         s_not_saved   //< inode is not saved in the archive
00069     };
00070 
00072     struct entree_stats
00073     {
00074         infinint num_x;                  //< number of file referenced as destroyed since last backup
00075         infinint num_d;                  //< number of directories
00076         infinint num_f;                  //< number of plain files (hard link or not, thus file directory entries)
00077         infinint num_c;                  //< number of char devices
00078         infinint num_b;                  //< number of block devices
00079         infinint num_p;                  //< number of named pipes
00080         infinint num_s;                  //< number of unix sockets
00081         infinint num_l;                  //< number of symbolic links
00082         infinint num_D;                  //< number of Door
00083         infinint num_hard_linked_inodes; //< number of inode that have more than one link (inode with "hard links")
00084         infinint num_hard_link_entries;  //< total number of hard links (file directory entry pointing to \an
00085             //< inode already linked in the same or another directory (i.e. hard linked))
00086         infinint saved; //< total number of saved inode (unix inode, not inode class) hard links do not count here
00087         infinint total; //< total number of inode in archive (unix inode, not inode class) hard links do not count here
00088         void clear() { num_x = num_d = num_f = num_c = num_b = num_p
00089                 = num_s = num_l = num_D = num_hard_linked_inodes
00090                 = num_hard_link_entries = saved = total = 0; };
00091         void add(const entree *ref);
00092         void listing(user_interaction & dialog) const;
00093     };
00094 
00096     class entree
00097     {
00098     public :
00099         static entree *read(user_interaction & dialog,
00100                             generic_file & f, const archive_version & reading_ver,
00101                             entree_stats & stats,
00102                             std::map <infinint, etoile *> & corres,
00103                             compression default_algo,
00104                             generic_file *data_loc,
00105                             generic_file *ea_loc,
00106                             bool lax,
00107                             bool only_detruit,
00108                             escape *ptr);
00109 
00110         virtual ~entree() {};
00111 
00113 
00120         void dump(generic_file & f, bool small) const;
00121 
00123 
00130         void specific_dump(generic_file & f, bool small) const { inherited_dump(f, small); };
00131 
00133 
00136         virtual void post_constructor(generic_file & f) {};
00137 
00138 
00139         virtual unsigned char signature() const = 0;
00140         virtual entree *clone() const = 0;
00141 
00142 #ifdef LIBDAR_SPECIAL_ALLOC
00143         USE_SPECIAL_ALLOC(entree);
00144 #endif
00145 
00146     protected:
00147         virtual void inherited_dump(generic_file & f, bool small) const;
00148 
00149 
00150     private:
00151         static const U_I ENTREE_CRC_SIZE;
00152 
00153     };
00154 
00155     extern bool compatible_signature(unsigned char a, unsigned char b);
00156     extern unsigned char mk_signature(unsigned char base, saved_status state);
00157 
00159     class eod : public entree
00160     {
00161     public :
00162         eod() {};
00163         eod(generic_file & f) {};
00164             // dump defined by entree
00165         unsigned char signature() const { return 'z'; };
00166         entree *clone() const { return new eod(); };
00167 
00168 
00169 #ifdef LIBDAR_SPECIAL_ALLOC
00170         USE_SPECIAL_ALLOC(eod);
00171 #endif
00172     };
00173 
00175     class nomme : public entree
00176     {
00177     public:
00178         nomme(const std::string & name) { xname = name; };
00179         nomme(generic_file & f);
00180         virtual bool operator == (const nomme & ref) const { return xname == ref.xname; };
00181         virtual bool operator < (const nomme & ref) const { return xname < ref.xname; };
00182 
00183         const std::string & get_name() const { return xname; };
00184         void change_name(const std::string & x) { xname = x; };
00185         bool same_as(const nomme & ref) const { return xname == ref.xname; };
00186             // no need to have a virtual method, as signature will differ in inherited classes (argument type changes)
00187 
00188             // signature() is kept as an abstract method
00189             // clone() is abstract
00190 
00191 #ifdef LIBDAR_SPECIAL_ALLOC
00192         USE_SPECIAL_ALLOC(nomme);
00193 #endif
00194 
00195     protected:
00196         void inherited_dump(generic_file & f, bool small) const;
00197 
00198     private:
00199         std::string xname;
00200     };
00201 
00202 
00204     class inode : public nomme
00205     {
00206     public:
00207 
00209 
00210         enum comparison_fields
00211         {
00212             cf_all,          //< consider any available field for comparing inodes
00213             cf_ignore_owner, //< consider any available field except ownership fields
00214             cf_mtime,        //< consider any available field except ownership and permission fields
00215             cf_inode_type    //< only consider the file type
00216         };
00217 
00218         inode(const infinint & xuid, const infinint & xgid, U_16 xperm,
00219               const infinint & last_access,
00220               const infinint & last_modif,
00221               const infinint & last_change,
00222               const std::string & xname, const infinint & device);
00223         inode(user_interaction & dialog,
00224               generic_file & f,
00225               const archive_version & reading_ver,
00226               saved_status saved,
00227               generic_file *ea_loc,
00228               escape *ptr);      // if ptr is not NULL, reading a partial dump(), which was done with "small" set to true
00229         inode(const inode & ref);
00230         const inode & operator = (const inode & ref);
00231         ~inode();
00232 
00233         const infinint & get_uid() const { return uid; };
00234         const infinint & get_gid() const { return gid; };
00235         U_16 get_perm() const { return perm; };
00236         infinint get_last_access() const { return *last_acc; };
00237         infinint get_last_modif() const { return *last_mod; };
00238         void set_last_access(const infinint & x_time) { *last_acc = x_time; };
00239         void set_last_modif(const infinint & x_time) { *last_mod = x_time; };
00240         saved_status get_saved_status() const { return xsaved; };
00241         void set_saved_status(saved_status x) { xsaved = x; };
00242         infinint get_device() const { return *fs_dev; };
00243 
00244         bool same_as(const inode & ref) const;
00245         bool is_more_recent_than(const inode & ref, const infinint & hourshift) const;
00246             // used for RESTORATION
00247         virtual bool has_changed_since(const inode & ref, const infinint & hourshift, comparison_fields what_to_check) const;
00248             // signature() left as an abstract method
00249             // clone is abstract too
00250             // used for INCREMENTAL BACKUP
00251         void compare(const inode &other,
00252                      const mask & ea_mask,
00253                      comparison_fields what_to_check,
00254                      const infinint & hourshift,
00255                      bool symlink_date) const;
00256 
00257             // throw Erange exception if a difference has been detected
00258             // this is not a symetrical comparison, but all what is present
00259             // in the current object is compared against the argument
00260             // which may contain supplementary informations
00261             // used for DIFFERENCE
00262 
00263 
00264 
00266             // EXTENDED ATTRIBUTS Methods
00267             //
00268 
00269         enum ea_status { ea_none, ea_partial, ea_fake, ea_full, ea_removed };
00270             // ea_none    : no EA present for this inode in filesystem
00271             // ea_partial : EA present in filesystem but not stored (ctime used to check changes)
00272             // ea_fake    : EA present in filesystem but not attached to this inode (isolation context) no more used in archive version "08" and above, ea_partial or ea_full stays a valid status in isolated catalogue because pointers to EA and data are no more removed during isolation process.
00273             // ea_full    : EA present in filesystem and attached to this inode
00274             // ea_removed : EA were present in the reference version, but not present anymore
00275 
00276             // I : to know whether EA data is present or not for this object
00277         void ea_set_saved_status(ea_status status);
00278         ea_status ea_get_saved_status() const { return ea_saved; };
00279 
00280             // II : to associate EA list to an inode object (mainly for backup operation) #EA_FULL only#
00281         void ea_attach(ea_attributs *ref);
00282         const ea_attributs *get_ea() const;              //   #<-- EA_FULL *and* EA_REMOVED# for this call only
00283         void ea_detach() const; //discards any future call to get_ea() !
00284         infinint ea_get_size() const; //returns the size of EA (still valid if ea have been detached)
00285 
00286             // III : to record where is dump the EA in the archive #EA_FULL only#
00287         void ea_set_offset(const infinint & pos) { *ea_offset = pos; };
00288         void ea_set_crc(const crc & val);
00289         void ea_get_crc(const crc * & ptr) const; //< the argument is set the an allocated crc object owned by this "inode" object, this reference stays valid while the "inode" object exists and MUST NOT be deleted by the caller in any case
00290         bool ea_get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument
00291 
00292             // IV : to know/record if EA have been modified # any EA status#
00293         infinint get_last_change() const;
00294         void set_last_change(const infinint & x_time);
00295         bool has_last_change() const { return last_cha != NULL; };
00296             // old format did provide last_change only when EA were present, since archive
00297             // format 8, this field is always present even in absence of EA. Thus it is
00298             // still necessary to check if the inode has a last_change() before
00299             // using get_last_change() (depends on the version of the archive read).
00300 
00301 
00302             // V : for archive migration (merging)
00303         void change_ea_location(generic_file *loc) { storage = loc; };
00304 
00306 
00307 #ifdef LIBDAR_SPECIAL_ALLOC
00308         USE_SPECIAL_ALLOC(inode);
00309 #endif
00310 
00311     protected:
00312         virtual void sub_compare(const inode & other) const {};
00313 
00315         escape *get_escape_layer() const { return esc; };
00316 
00317         void inherited_dump(generic_file & f, bool small) const;
00318 
00319     private :
00320         infinint uid;
00321         infinint gid;
00322         U_16 perm;
00323         infinint *last_acc, *last_mod;
00324         saved_status xsaved;
00325         ea_status ea_saved;
00326             //  the following is used only if ea_saved == full
00327         infinint *ea_offset;
00328         ea_attributs *ea;
00329         infinint ea_size;
00330             // the following is used if ea_saved == full or ea_saved == partial
00331         infinint *last_cha;
00332         crc *ea_crc;
00333         infinint *fs_dev;
00334         generic_file *storage; // where are stored EA
00335         archive_version edit;   // need to know EA format used in archive file
00336 
00337         escape *esc;  // if not NULL, the object is partially build from archive (at archive generation, dump() was called with small set to true)
00338 
00339         static const ea_attributs empty_ea;
00340     };
00341 
00343     class etoile
00344     {
00345     public:
00346 
00348 
00352         etoile(inode *host, const infinint & etiquette_number);
00353         etoile(const etoile & ref) { throw SRC_BUG; }; // copy constructor not allowed for this class
00354         const etoile & operator = (const etoile & ref) { throw SRC_BUG; }; // assignment not allowed for this class
00355         ~etoile() { delete hosted; };
00356 
00357         void add_ref(void *ref);
00358         void drop_ref(void *ref);
00359         infinint get_ref_count() const { return refs.size(); };
00360         inode *get_inode() const { return hosted; };
00361         infinint get_etiquette() const { return etiquette; };
00362         void change_etiquette(const infinint & new_val) { etiquette = new_val; };
00363 
00364 
00365         bool is_counted() const { return tags.counted; };
00366         bool is_wrote() const { return tags.wrote; };
00367         bool is_dumped() const { return tags.dumped; };
00368         void set_counted(bool val) { tags.counted = val ? 1 : 0; };
00369         void set_wrote(bool val) { tags.wrote = val ? 1 : 0; };
00370         void set_dumped(bool val) { tags.dumped = val ? 1 : 0; };
00371 
00372             // return the address of the first mirage that triggered the creation of this mirage
00373             // if this object is destroyed afterward this call returns NULL
00374         const void *get_first_ref() const { if(refs.size() == 0) throw SRC_BUG; return refs.front(); };
00375 
00376 #ifdef LIBDAR_SPECIAL_ALLOC
00377         USE_SPECIAL_ALLOC(etoile);
00378 #endif
00379 
00380     private:
00381         struct bool_tags
00382         {
00383             unsigned counted : 1; //< whether the inode has been counted
00384             unsigned wrote : 1;   //< whether the inode has its data copied to archive
00385             unsigned dumped : 1;  //< whether the inode information has been dumped in the catalogue
00386             unsigned : 5;         //< padding to get byte boundary and reserved for future use.
00387 
00388             bool_tags() { counted = wrote = dumped = 0; };
00389         };
00390 
00391         std::list<void *> refs; //< list of pointers to the mirages objects, in the order of their creation
00392         inode *hosted;
00393         infinint etiquette;
00394         bool_tags tags;
00395     };
00396 
00398 
00400     class mirage : public nomme
00401     {
00402     public:
00403         enum mirage_format {fmt_mirage,           //< new format
00404                             fmt_hard_link,        //< old dual format
00405                             fmt_file_etiquette }; //< old dual format
00406 
00407         mirage(const std::string & name, etoile *ref) : nomme(name) { star_ref = ref; if(ref == NULL) throw SRC_BUG; star_ref->add_ref(this); };
00408         mirage(user_interaction & dialog,
00409                generic_file & f,
00410                const archive_version & reading_ver,
00411                saved_status saved,
00412                entree_stats & stats,
00413                std::map <infinint, etoile *> & corres,
00414                compression default_algo,
00415                generic_file *data_loc,
00416                generic_file *ea_loc,
00417                mirage_format fmt,
00418                bool lax,
00419                escape *ptr);
00420         mirage(user_interaction & dialog,
00421                generic_file & f,
00422                const archive_version & reading_ver,
00423                saved_status saved,
00424                entree_stats & stats,
00425                std::map <infinint, etoile *> & corres,
00426                compression default_algo,
00427                generic_file *data_loc,
00428                generic_file *ea_loc,
00429                bool lax,
00430                escape *ptr);
00431         mirage(const mirage & ref) : nomme (ref) { star_ref = ref.star_ref; if(star_ref == NULL) throw SRC_BUG; star_ref->add_ref(this); };
00432         const mirage & operator = (const mirage & ref);
00433         ~mirage() { star_ref->drop_ref(this); };
00434 
00435         unsigned char signature() const { return 'm'; };
00436         entree *clone() const { return new mirage(*this); };
00437 
00438         inode *get_inode() const { if(star_ref == NULL) throw SRC_BUG; return star_ref->get_inode(); };
00439         infinint get_etiquette() const { return star_ref->get_etiquette(); };
00440         infinint get_etoile_ref_count() const { return star_ref->get_ref_count(); };
00441         etoile *get_etoile() const { return star_ref; };
00442 
00443         bool is_inode_counted() const { return star_ref->is_counted(); };
00444         bool is_inode_wrote() const { return star_ref->is_wrote(); };
00445         bool is_inode_dumped() const { return star_ref->is_dumped(); };
00446         void set_inode_counted(bool val) const { star_ref->set_counted(val); };
00447         void set_inode_wrote(bool val) const { star_ref->set_wrote(val); };
00448         void set_inode_dumped(bool val) const { star_ref->set_dumped(val); };
00449 
00450         void post_constructor(generic_file & f);
00451 
00453         bool is_first_mirage() const { return star_ref->get_first_ref() == this; };
00454 
00455 #ifdef LIBDAR_SPECIAL_ALLOC
00456         USE_SPECIAL_ALLOC(mirage);
00457 #endif
00458 
00459     protected:
00460         void inherited_dump(generic_file & f, bool small) const;
00461 
00462     private:
00463         etoile *star_ref;
00464 
00465         void init(user_interaction & dialog,
00466                   generic_file & f,
00467                   const archive_version & reading_ver,
00468                   saved_status saved,
00469                   entree_stats & stats,
00470                   std::map <infinint, etoile *> & corres,
00471                   compression default_algo,
00472                   generic_file *data_loc,
00473                   generic_file *ea_loc,
00474                   mirage_format fmt,
00475                   bool lax,
00476                   escape *ptr);
00477     };
00478 
00479 
00481     class file : public inode
00482     {
00483     public :
00484         enum get_data_mode
00485         {
00486             keep_compressed, //< provide access to compressed data
00487             keep_hole,       //< provide access to uncompressed data but sparse_file datastructure
00488             normal,          //< provide access to full data (uncompressed, uses skip() to restore holes)
00489             plain            //< provide access to plain data, no skip to restore holes, provide instead zeroed bytes
00490         };
00491 
00492         static const U_8 FILE_DATA_WITH_HOLE = 0x01; //< file's data contains hole datastructure
00493         static const U_8 FILE_DATA_IS_DIRTY = 0x02;  //< data modified while being saved
00494 
00495         file(const infinint & xuid, const infinint & xgid, U_16 xperm,
00496              const infinint & last_access,
00497              const infinint & last_modif,
00498              const infinint & last_change,
00499              const std::string & src,
00500              const path & che,
00501              const infinint & taille,
00502              const infinint & fs_device,
00503              bool x_furtive_read_mode);
00504         file(const file & ref);
00505         file(user_interaction & dialog,
00506              generic_file & f,
00507              const archive_version & reading_ver,
00508              saved_status saved,
00509              compression default_algo,
00510              generic_file *data_loc,
00511              generic_file *ea_loc,
00512              escape *ptr);
00513         ~file() { detruit(); };
00514 
00515         bool has_changed_since(const inode & ref, const infinint & hourshift, inode::comparison_fields what_to_check) const;
00516         infinint get_size() const { return *size; };
00517         infinint get_storage_size() const { return *storage_size; };
00518         void set_storage_size(const infinint & s) { *storage_size = s; };
00519         virtual generic_file *get_data(get_data_mode mode) const; // returns a newly allocated object in read_only mode
00520         void clean_data(); // partially free memory (but get_data() becomes disabled)
00521         void set_offset(const infinint & r);
00522         const infinint & get_offset() const;
00523         unsigned char signature() const { return mk_signature('f', get_saved_status()); };
00524 
00525         void set_crc(const crc &c);
00526         bool get_crc(const crc * & c) const; //< the argument is set the an allocated crc object the owned by the "file" object, its stay valid while this "file" object exists and MUST NOT be deleted by the caller in any case
00527         bool has_crc() const { return check != NULL; };
00528         bool get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument
00529         void drop_crc() { if(check != NULL) { delete check; check = NULL; } };
00530 
00531             // whether the plain file has to detect sparse file
00532         void set_sparse_file_detection_read(bool val) { if(status == from_cat) throw SRC_BUG; if(val) file_data_status_read |= FILE_DATA_WITH_HOLE; else file_data_status_read &= ~FILE_DATA_WITH_HOLE; };
00533 
00534         void set_sparse_file_detection_write(bool val) { if(val) file_data_status_write |= FILE_DATA_WITH_HOLE; else file_data_status_write &= ~FILE_DATA_WITH_HOLE; };
00535 
00536             // whether the plain file is stored with a sparse_file datastructure in the archive
00537         bool get_sparse_file_detection_read() const { return (file_data_status_read & FILE_DATA_WITH_HOLE) != 0; };
00538         bool get_sparse_file_detection_write() const { return (file_data_status_write & FILE_DATA_WITH_HOLE) != 0; };
00539 
00540         entree *clone() const { return new file(*this); };
00541 
00542         compression get_compression_algo_read() const { return algo_read; };
00543 
00544         compression get_compression_algo_write() const { return algo_write; };
00545 
00546             // object migration methods (merging)
00547         void change_compression_algo_write(compression x) { algo_write = x; };
00548         void change_location(generic_file *x) { loc = x; };
00549 
00550             // dirtiness
00551 
00552         bool is_dirty() const { return dirty; };
00553         void set_dirty(bool value) { dirty = value; };
00554 
00555 #ifdef LIBDAR_SPECIAL_ALLOC
00556         USE_SPECIAL_ALLOC(file);
00557 #endif
00558 
00559     protected:
00560         void sub_compare(const inode & other) const;
00561         void inherited_dump(generic_file & f, bool small) const;
00562         void post_constructor(generic_file & f);
00563 
00564         enum { empty, from_path, from_cat } status;
00565 
00566     private:
00567         std::string chemin;     //< path to the data (when read from filesystem)
00568         infinint *offset;       //< start location of the data in 'loc'
00569         infinint *size;         //< size of the data (uncompressed)
00570         infinint *storage_size; //< how much data used in archive (after compression)
00571         crc *check;
00572         bool dirty;     //< true when a file has been modified at the time it was saved
00573 
00574         generic_file *loc;      //< where to find data (eventually compressed) at the recorded offset and for storage_size length
00575         compression algo_read;  //< which compression algorithm to use to read the file's data
00576         compression algo_write; //< which compression algorithm to use to write down (merging) the file's data
00577         bool furtive_read_mode; // used only when status equals "from_path"
00578         char file_data_status_read; // defines the datastructure to use when reading the data
00579         char file_data_status_write; // defines the datastructure to apply when writing down the data
00580 
00581         void detruit();
00582     };
00583 
00585     class door : public file
00586     {
00587     public:
00588         door(const infinint & xuid, const infinint & xgid, U_16 xperm,
00589              const infinint & last_access,
00590              const infinint & last_modif,
00591              const infinint & last_change,
00592              const std::string & src,
00593              const path & che,
00594              const infinint & fs_device) : file(xuid, xgid, xperm, last_access, last_modif,
00595                                                 last_change, src, che, 0, fs_device, false) {};
00596         door(user_interaction & dialog,
00597              generic_file & f,
00598              const archive_version & reading_ver,
00599              saved_status saved,
00600              compression default_algo,
00601              generic_file *data_loc,
00602              generic_file *ea_loc,
00603              escape *ptr) : file(dialog, f, reading_ver, saved, default_algo, data_loc, ea_loc, ptr) {};
00604 
00605         unsigned char signature() const { return mk_signature('o', get_saved_status()); };
00606 
00607         generic_file *get_data(get_data_mode mode) const; // inherited from class file
00608 
00609 #ifdef LIBDAR_SPECIAL_ALLOC
00610         USE_SPECIAL_ALLOC(door);
00611 #endif
00612     };
00613 
00615     class lien : public inode
00616     {
00617     public :
00618         lien(const infinint & uid, const infinint & gid, U_16 perm,
00619              const infinint & last_access,
00620              const infinint & last_modif,
00621              const infinint & last_change,
00622              const std::string & name,
00623              const std::string & target,
00624              const infinint & fs_device);
00625         lien(user_interaction & dialog,
00626              generic_file & f,
00627              const archive_version & reading_ver,
00628              saved_status saved,
00629              generic_file *ea_loc,
00630              escape *ptr);
00631 
00632         const std::string & get_target() const;
00633         void set_target(std::string x);
00634 
00635             // using the method is_more_recent_than() from inode
00636             // using method has_changed_since() from inode class
00637         unsigned char signature() const { return mk_signature('l', get_saved_status()); };
00638         entree *clone() const { return new lien(*this); };
00639 
00640 #ifdef LIBDAR_SPECIAL_ALLOC
00641         USE_SPECIAL_ALLOC(lien);
00642 #endif
00643     protected :
00644         void sub_compare(const inode & other) const;
00645         void inherited_dump(generic_file & f, bool small) const;
00646 
00647 
00648     private :
00649         std::string points_to;
00650     };
00651 
00653     class directory : public inode
00654     {
00655     public :
00656         directory(const infinint & xuid, const infinint & xgid, U_16 xperm,
00657                   const infinint & last_access,
00658                   const infinint & last_modif,
00659                   const infinint & last_change,
00660                   const std::string & xname,
00661                   const infinint & device);
00662         directory(const directory &ref); // only the inode part is build, no children is duplicated (empty dir)
00663         const directory & operator = (const directory & ref); // set the inode part *only* no subdirectories/subfiles are copies or removed.
00664         directory(user_interaction & dialog,
00665                   generic_file & f,
00666                   const archive_version & reading_ver,
00667                   saved_status saved,
00668                   entree_stats & stats,
00669                   std::map <infinint, etoile *> & corres,
00670                   compression default_algo,
00671                   generic_file *data_loc,
00672                   generic_file *ea_loc,
00673                   bool lax,
00674                   bool only_detruit, // objects of other class than detruit and directory are not built in memory
00675                   escape *ptr);
00676         ~directory(); // detruit aussi tous les fils et se supprime de son 'parent'
00677 
00678         void add_children(nomme *r); // when r is a directory, 'parent' is set to 'this'
00679         bool has_children() const { return !ordered_fils.empty(); };
00680         void reset_read_children() const;
00681         void end_read() const;
00682         bool read_children(const nomme * &r) const; // read the direct children of the directory, returns false if no more is available
00683             // remove all entry not yet read by read_children
00684         void tail_to_read_children();
00685 
00686         void remove(const std::string & name); // remove the given entry from the catalogue
00687             // as side effect the reset_read_children() method must be called.
00688 
00689         directory * get_parent() const { return parent; };
00690         bool search_children(const std::string &name, nomme *&ref);
00691         bool callback_for_children_of(user_interaction & dialog, const std::string & sdir, bool isolated = false) const;
00692 
00693             // using is_more_recent_than() from inode class
00694             // using method has_changed_since() from inode class
00695         unsigned char signature() const { return mk_signature('d', get_saved_status()); };
00696 
00697             // some data has changed since archive of reference in this directory or subdirectories
00698         bool get_recursive_has_changed() const { return recursive_has_changed; };
00699             // update the recursive_has_changed field
00700         void recursive_has_changed_update() const;
00701 
00702             // get then number of "nomme" entry contained in this directory and subdirectories (recursive call)
00703         infinint get_tree_size() const;
00704             // get the number of entry having some EA set in the directory tree (recursive call)
00705         infinint get_tree_ea_num() const;
00706             // get the number of entry that are hard linked inode (aka mirage in dar implementation) (recursive call)
00707         infinint get_tree_mirage_num() const;
00708             // for each mirage found (hard link implementation) in the directory tree, add its etiquette to the returned
00709             // list with the number of reference that has been found in the tree. (map[etiquette] = number of occurence)
00710             // from outside of class directory, the given argument is expected to be an empty map.
00711         void get_etiquettes_found_in_tree(std::map<infinint, infinint> & already_found) const;
00712 
00713             // whether this directory is empty or not
00714         bool is_empty() const { return ordered_fils.empty(); };
00715 
00716             // recursively remove all mirage entries
00717         void remove_all_mirages_and_reduce_dirs();
00718 
00719         entree *clone() const { return new directory(*this); };
00720 
00721 #ifdef LIBDAR_SPECIAL_ALLOC
00722         USE_SPECIAL_ALLOC(directory);
00723 #endif
00724 
00725     protected:
00726         void inherited_dump(generic_file & f, bool small) const;
00727 
00728     private :
00729         static const eod fin;
00730 
00731         directory *parent;
00732 #ifdef LIBDAR_FAST_DIR
00733         std::map<std::string, nomme *> fils; // used for fast lookup
00734 #endif
00735         std::list<nomme *> ordered_fils;
00736         std::list<nomme *>::iterator it;
00737         bool recursive_has_changed;
00738 
00739         void clear();
00740     };
00741 
00743     class device : public inode
00744     {
00745     public :
00746         device(const infinint & uid, const infinint & gid, U_16 perm,
00747                const infinint & last_access,
00748                const infinint & last_modif,
00749                const infinint &last_change,
00750                const std::string & name,
00751                U_16 major,
00752                U_16 minor,
00753                const infinint & fs_device);
00754         device(user_interaction & dialog,
00755                generic_file & f,
00756                const archive_version & reading_ver,
00757                saved_status saved,
00758                generic_file *ea_loc,
00759                escape *ptr);
00760 
00761         int get_major() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xmajor; };
00762         int get_minor() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xminor; };
00763         void set_major(int x) { xmajor = x; };
00764         void set_minor(int x) { xminor = x; };
00765 
00766             // using method is_more_recent_than() from inode class
00767             // using method has_changed_since() from inode class
00768             // signature is left pure abstract
00769 
00770 #ifdef LIBDAR_SPECIAL_ALLOC
00771         USE_SPECIAL_ALLOC(device);
00772 #endif
00773 
00774     protected :
00775         void sub_compare(const inode & other) const;
00776         void inherited_dump(generic_file & f, bool small) const;
00777 
00778     private :
00779         U_16 xmajor, xminor;
00780     };
00781 
00783     class chardev : public device
00784     {
00785     public:
00786         chardev(const infinint & uid, const infinint & gid, U_16 perm,
00787                 const infinint & last_access,
00788                 const infinint & last_modif,
00789                 const infinint & last_change,
00790                 const std::string & name,
00791                 U_16 major,
00792                 U_16 minor,
00793                 const infinint & fs_device) : device(uid, gid, perm,
00794                                                      last_access,
00795                                                      last_modif,
00796                                                      last_change,
00797                                                      name,
00798                                                      major, minor, fs_device) {};
00799         chardev(user_interaction & dialog,
00800                 generic_file & f,
00801                 const archive_version & reading_ver,
00802                 saved_status saved,
00803                 generic_file *ea_loc,
00804                 escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00805 
00806             // using dump from device class
00807             // using method is_more_recent_than() from device class
00808             // using method has_changed_since() from device class
00809         unsigned char signature() const { return mk_signature('c', get_saved_status()); };
00810         entree *clone() const { return new chardev(*this); };
00811 
00812 #ifdef LIBDAR_SPECIAL_ALLOC
00813         USE_SPECIAL_ALLOC(chardev);
00814 #endif
00815     };
00816 
00818     class blockdev : public device
00819     {
00820     public:
00821         blockdev(const infinint & uid, const infinint & gid, U_16 perm,
00822                  const infinint & last_access,
00823                  const infinint & last_modif,
00824                  const infinint & last_change,
00825                  const std::string & name,
00826                  U_16 major,
00827                  U_16 minor,
00828                  const infinint & fs_device) : device(uid, gid, perm, last_access,
00829                                                       last_modif, last_change, name,
00830                                                       major, minor, fs_device) {};
00831         blockdev(user_interaction & dialog,
00832                  generic_file & f,
00833                  const archive_version & reading_ver,
00834                  saved_status saved,
00835                  generic_file *ea_loc,
00836                  escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00837 
00838             // using dump from device class
00839             // using method is_more_recent_than() from device class
00840             // using method has_changed_since() from device class
00841         unsigned char signature() const { return mk_signature('b', get_saved_status()); };
00842         entree *clone() const { return new blockdev(*this); };
00843 
00844 #ifdef LIBDAR_SPECIAL_ALLOC
00845         USE_SPECIAL_ALLOC(blockdev);
00846 #endif
00847     };
00848 
00850     class tube : public inode
00851     {
00852     public :
00853         tube(const infinint & xuid, const infinint & xgid, U_16 xperm,
00854              const infinint & last_access,
00855              const infinint & last_modif,
00856              const infinint & last_change,
00857              const std::string & xname,
00858              const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); };
00859         tube(user_interaction & dialog,
00860              generic_file & f,
00861              const archive_version & reading_ver,
00862              saved_status saved,
00863              generic_file *ea_loc,
00864              escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00865 
00866             // using dump from inode class
00867             // using method is_more_recent_than() from inode class
00868             // using method has_changed_since() from inode class
00869         unsigned char signature() const { return mk_signature('p', get_saved_status()); };
00870         entree *clone() const { return new tube(*this); };
00871 
00872 #ifdef LIBDAR_SPECIAL_ALLOC
00873         USE_SPECIAL_ALLOC(tube);
00874 #endif
00875     };
00876 
00878     class prise : public inode
00879     {
00880     public :
00881         prise(const infinint & xuid, const infinint & xgid, U_16 xperm,
00882               const infinint & last_access,
00883               const infinint & last_modif,
00884               const infinint & last_change,
00885               const std::string & xname,
00886               const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); };
00887         prise(user_interaction & dialog,
00888               generic_file & f,
00889               const archive_version & reading_ver,
00890               saved_status saved,
00891               generic_file *ea_loc,
00892               escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00893 
00894             // using dump from inode class
00895             // using method is_more_recent_than() from inode class
00896             // using method has_changed_since() from inode class
00897         unsigned char signature() const { return mk_signature('s', get_saved_status()); };
00898         entree *clone() const { return new prise(*this); };
00899 
00900 #ifdef LIBDAR_SPECIAL_ALLOC
00901         USE_SPECIAL_ALLOC(prise);
00902 #endif
00903     };
00904 
00906     class detruit : public nomme
00907     {
00908     public :
00909         detruit(const std::string & name, unsigned char firm, const infinint & date) : nomme(name) , del_date(date) { signe = firm; };
00910         detruit(generic_file & f, const archive_version & reading_ver);
00911         detruit(const nomme &ref) : nomme(ref.get_name()), del_date(0) { signe = ref.signature(); };
00912 
00913         unsigned char get_signature() const { return signe; };
00914         void set_signature(unsigned char x) { signe = x; };
00915         unsigned char signature() const { return 'x'; };
00916         entree *clone() const { return new detruit(*this); };
00917 
00918         const infinint & get_date() const { return del_date; };
00919         void set_date(const infinint & ref) { del_date = ref; };
00920 
00921 #ifdef LIBDAR_SPECIAL_ALLOC
00922         USE_SPECIAL_ALLOC(detruit);
00923 #endif
00924     protected:
00925         void inherited_dump(generic_file & f, bool small) const;
00926 
00927     private :
00928         unsigned char signe;
00929         infinint del_date;
00930     };
00931 
00933     class ignored : public nomme
00934     {
00935     public :
00936         ignored(const std::string & name) : nomme(name) {};
00937         ignored(generic_file & f) : nomme(f) { throw SRC_BUG; };
00938 
00939         unsigned char signature() const { return 'i'; };
00940         entree *clone() const { return new ignored(*this); };
00941 #ifdef LIBDAR_SPECIAL_ALLOC
00942         USE_SPECIAL_ALLOC(ignored);
00943 #endif
00944 
00945     protected:
00946         void inherited_dump(generic_file & f, bool small) const { throw SRC_BUG; };
00947 
00948     };
00949 
00951     class ignored_dir : public inode
00952     {
00953     public:
00954         ignored_dir(const directory &target) : inode(target) {};
00955         ignored_dir(user_interaction & dialog,
00956                     generic_file & f,
00957                     const archive_version & reading_ver,
00958                     generic_file *ea_loc,
00959                     escape *ptr) : inode(dialog, f, reading_ver, s_not_saved, ea_loc, ptr) { throw SRC_BUG; };
00960 
00961         unsigned char signature() const { return 'j'; };
00962         entree *clone() const { return new ignored_dir(*this); };
00963 #ifdef LIBDAR_SPECIAL_ALLOC
00964         USE_SPECIAL_ALLOC(ignored_dir);
00965 #endif
00966 
00967     protected:
00968         void inherited_dump(generic_file & f, bool small) const; // behaves like an empty directory
00969 
00970     };
00971 
00973     class catalogue : protected mem_ui
00974     {
00975     public :
00976         catalogue(user_interaction & dialog,
00977                   const infinint & root_last_modif,
00978                   const label & data_name);
00979         catalogue(user_interaction & dialog,
00980                   generic_file & f,
00981                   const archive_version & reading_ver,
00982                   compression default_algo,
00983                   generic_file *data_loc,
00984                   generic_file *ea_loc,
00985                   bool lax,
00986                   const label & lax_layer1_data_name, //< ignored unless in lax mode, in lax mode unless it is a cleared label, forces the catalogue label to be equal to the lax_layer1_data_name for it be considered a plain internal catalogue, even in case of corruption
00987                   bool only_detruit = false); //< if set to true, only directories and detruit objects are read from the archive
00988         catalogue(const catalogue & ref) : mem_ui(ref), out_compare(ref.out_compare) { partial_copy_from(ref); };
00989         const catalogue & operator = (const catalogue &ref);
00990         virtual ~catalogue() { detruire(); };
00991 
00992 
00993             // reading methods. The reading is iterative and uses the current_read directory pointer
00994 
00995         virtual void reset_read() const; // set the reading cursor to the beginning of the catalogue
00996         virtual void end_read() const; // set the reading cursor to the end of the catalogue
00997         virtual void skip_read_to_parent_dir() const;
00998             // skip all items of the current dir and of any subdir, the next call will return
00999             // next item of the parent dir (no eod to exit from the current dir !)
01000         virtual bool read(const entree * & ref) const;
01001             // sequential read (generates eod) and return false when all files have been read
01002         virtual bool read_if_present(std::string *name, const nomme * & ref) const;
01003             // pseudo-sequential read (reading a directory still
01004             // implies that following read are located in this subdirectory up to the next EOD) but
01005             // it returns false if no entry of this name are present in the current directory
01006             // a call with NULL as first argument means to set the current dir the parent directory
01007         void remove_read_entry(std::string & name);
01008             // in the currently read directory, removes the entry which name is given in argument
01009         const directory & get_current_reading_dir() const { return *current_read; };
01010             // remove from the catalogue all the entries that have not yet been read
01011             // by read().
01012         void tail_catalogue_to_current_read();
01013 
01014 
01015         void reset_sub_read(const path &sub); // initialise sub_read to the given directory
01016         bool sub_read(const entree * &ref); // sequential read of the catalogue, ignoring all that
01017             // is not part of the subdirectory specified with reset_sub_read
01018             // the read include the inode leading to the sub_tree as well as the pending eod
01019 
01020             // return true if the last read entry has already been read
01021             // and has not to be counted again. This is never the case for catalogue but may occure
01022             // with escape_catalogue (where from the 'virtual').
01023             // last this method gives a valid result only if the last read() entry is a directory as
01024             // only directory may be read() twice.
01025         virtual bool read_second_time_dir() const { return false; };
01026 
01027 
01028             // Additions methods. The addition is also iterative but uses its specific current_add directory pointer
01029 
01030         void reset_add();
01031 
01033             // real implementation is only needed in escape_catalogue class, here there nothing to be done
01034         virtual void pre_add(const entree *ref, compressor *compr) const {};
01035         virtual void pre_add_ea(const entree *ref, compressor *compr) const {};
01036         virtual void pre_add_crc(const entree *ref, compressor *compr) const {};
01037         virtual void pre_add_dirty(compressor *compr) const {};
01038         virtual void pre_add_ea_crc(const entree *ref, compressor *compr) const {};
01039         virtual void pre_add_waste_mark(compressor *compr) const {};
01040         virtual void pre_add_failed_mark(compressor *compr) const {};
01041         virtual escape *get_escape_layer() const { return NULL; };
01042 
01043         void add(entree *ref); // add at end of catalogue (sequential point of view)
01044         void re_add_in(const std::string &subdirname); // return into an already existing subdirectory for further addition
01045         void re_add_in_replace(const directory &dir); // same as re_add_in but also set the properties of the existing directory to those of the given argument
01046         void add_in_current_read(nomme *ref); // add in currently read directory
01047 
01048 
01049 
01050             // Comparison methods. The comparision is here also iterative and uses its specific current_compare directory pointer
01051 
01052         void reset_compare();
01053         bool compare(const entree * name, const entree * & extracted);
01054             // returns true if the ref exists, and gives it back in second argument as it is in the current catalogue.
01055             // returns false is no entry of that nature exists in the catalogue (in the current directory)
01056             // if ref is a directory, the operation is normaly relative to the directory itself, but
01057             // such a call implies a chdir to that directory. thus, a call with an EOD is necessary to
01058             // change to the parent directory.
01059             // note :
01060             // if a directory is not present, returns false, but records the inexistant subdirectory
01061             // structure defined by the following calls to this routine, this to be able to know when
01062             // the last available directory is back the current one when changing to parent directory,
01063             // and then proceed with normal comparison of inode. In this laps of time, the call will
01064             // always return false, while it temporary stores the missing directory structure
01065 
01066 
01067 
01068             // non interative methods
01069 
01070         bool direct_read(const path & ref, const nomme * &ret);
01071         infinint update_destroyed_with(catalogue & ref);
01072             // ref must have the same root, else the operation generates an exception
01073 
01074         void update_absent_with(catalogue & ref, infinint aborting_next_etoile);
01075             // in case of abortion, completes missing files as if what could not be
01076             // inspected had not changed since the reference was done
01077             // aborting_last_etoile is the highest etoile reference withing "this" current object.
01078 
01079         void dump(generic_file & f) const;
01080         void listing(bool isolated,
01081                      const mask &selection,
01082                      const mask & subtree,
01083                      bool filter_unsaved,
01084                      bool list_ea,
01085                      std::string marge) const;
01086         void tar_listing(bool isolated,
01087                          const mask & selection,
01088                          const mask & subtree,
01089                          bool filter_unsaved,
01090                          bool list_ea,
01091                          std::string beginning) const;
01092         void xml_listing(bool isolated,
01093                          const mask & selection,
01094                          const mask & subtree,
01095                          bool filter_unsaved,
01096                          bool list_ea,
01097                          std::string beginning) const;
01098 
01099         entree_stats get_stats() const { return stats; };
01100 
01102         bool is_empty() const { if(contenu == NULL) throw SRC_BUG; return contenu->is_empty(); };
01103 
01104         const directory *get_contenu() const { return contenu; }; // used by data_tree
01105 
01106         const label & get_data_name() const { return ref_data_name; };
01107         infinint get_root_dir_last_modif() const { return contenu->get_last_modif(); };
01108 
01110         void launch_recursive_has_changed_update() const { contenu->recursive_has_changed_update(); };
01111 
01112         infinint get_root_mtime() const { return contenu->get_last_modif(); };
01113 
01115         void reset_all();
01116 
01117 
01118     protected:
01119         entree_stats & access_stats() { return stats; };
01120         void set_data_name(const label & val) { ref_data_name = val; };
01121         void copy_detruits_from(const catalogue & ref); // needed for escape_catalogue implementation only.
01122 
01123         const eod * get_r_eod_address() const { return & r_eod; }; // eod are never stored in the catalogue
01124             // however it is sometimes required to return such a reference to a valid object
01125             // owned by the catalogue.
01126 
01127 
01130         void swap_stuff(catalogue & ref);
01131 
01132     private :
01133         directory *contenu;               
01134         path out_compare;                 
01135         directory *current_compare;       
01136         directory *current_add;           
01137         directory *current_read;          
01138         path *sub_tree;                   
01139         signed int sub_count;             
01140         entree_stats stats;               
01141         label ref_data_name;              
01142 
01143         void partial_copy_from(const catalogue &ref);
01144         void detruire();
01145 
01146         static const eod r_eod;           // needed to return eod reference, without taking risk of saturating memory
01147         static const U_I CAT_CRC_SIZE;
01148     };
01149 
01150 
01151 
01153 
01154 } // end of namespace
01155 
01156 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines