Disk ARchive  2.4.12
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
catalogue.hpp
Go to the documentation of this file.
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 
00025 
00026 #ifndef CATALOGUE_HPP
00027 #define CATALOGUE_HPP
00028 
00029 #include "../my_config.h"
00030 
00031 extern "C"
00032 {
00033 #if HAVE_UNISTD_H
00034 #include <unistd.h>
00035 #endif
00036 } // end extern "C"
00037 
00038 #include <vector>
00039 #include <map>
00040 #include <new>
00041 #include "infinint.hpp"
00042 #include "generic_file.hpp"
00043 #include "path.hpp"
00044 #include "header_version.hpp"
00045 #include "ea.hpp"
00046 #include "compressor.hpp"
00047 #include "integers.hpp"
00048 #include "mask.hpp"
00049 #include "special_alloc.hpp"
00050 #include "user_interaction.hpp"
00051 #include "label.hpp"
00052 #include "escape.hpp"
00053 
00054 namespace libdar
00055 {
00056     class etoile;
00057     class entree;
00058 
00061 
00062     enum saved_status
00063     {
00064         s_saved,      //< inode is saved in the archive
00065         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.
00066         s_not_saved   //< inode is not saved in the archive
00067     };
00068 
00070     struct entree_stats
00071     {
00072         infinint num_x;                  //< number of file referenced as destroyed since last backup
00073         infinint num_d;                  //< number of directories
00074         infinint num_f;                  //< number of plain files (hard link or not, thus file directory entries)
00075         infinint num_c;                  //< number of char devices
00076         infinint num_b;                  //< number of block devices
00077         infinint num_p;                  //< number of named pipes
00078         infinint num_s;                  //< number of unix sockets
00079         infinint num_l;                  //< number of symbolic links
00080         infinint num_D;                  //< number of Door
00081         infinint num_hard_linked_inodes; //< number of inode that have more than one link (inode with "hard links")
00082         infinint num_hard_link_entries;  //< total number of hard links (file directory entry pointing to \an
00083             //< inode already linked in the same or another directory (i.e. hard linked))
00084         infinint saved; //< total number of saved inode (unix inode, not inode class) hard links do not count here
00085         infinint total; //< total number of inode in archive (unix inode, not inode class) hard links do not count here
00086         void clear() { num_x = num_d = num_f = num_c = num_b = num_p
00087                 = num_s = num_l = num_D = num_hard_linked_inodes
00088                 = num_hard_link_entries = saved = total = 0; };
00089         void add(const entree *ref);
00090         void listing(user_interaction & dialog) const;
00091     };
00092 
00094     class entree
00095     {
00096     public :
00097         static entree *read(user_interaction & dialog,
00098                             generic_file & f, const archive_version & reading_ver,
00099                             entree_stats & stats,
00100                             std::map <infinint, etoile *> & corres,
00101                             compression default_algo,
00102                             generic_file *data_loc,
00103                             generic_file *ea_loc,
00104                             bool lax,
00105                             bool only_detruit,
00106                             escape *ptr);
00107 
00108         virtual ~entree() {};
00109 
00111 
00118         void dump(generic_file & f, bool small) const;
00119 
00121 
00128         void specific_dump(generic_file & f, bool small) const { inherited_dump(f, small); };
00129 
00131 
00134         virtual void post_constructor(generic_file & f) {};
00135 
00136 
00137         virtual unsigned char signature() const = 0;
00138         virtual entree *clone() const = 0;
00139 
00140 #ifdef LIBDAR_SPECIAL_ALLOC
00141         USE_SPECIAL_ALLOC(entree);
00142 #endif
00143 
00144     protected:
00145         virtual void inherited_dump(generic_file & f, bool small) const;
00146 
00147 
00148     private:
00149         static const U_I ENTREE_CRC_SIZE;
00150 
00151     };
00152 
00153     extern bool compatible_signature(unsigned char a, unsigned char b);
00154     extern unsigned char mk_signature(unsigned char base, saved_status state);
00155     extern unsigned char get_base_signature(unsigned char a);
00156 
00158     class eod : public entree
00159     {
00160     public :
00161         eod() {};
00162         eod(generic_file & f) {};
00163             // dump defined by entree
00164         unsigned char signature() const { return 'z'; };
00165         entree *clone() const { return new (std::nothrow) eod(); };
00166 
00167 
00168 #ifdef LIBDAR_SPECIAL_ALLOC
00169         USE_SPECIAL_ALLOC(eod);
00170 #endif
00171     };
00172 
00174     class nomme : public entree
00175     {
00176     public:
00177         nomme(const std::string & name) { xname = name; };
00178         nomme(generic_file & f);
00179         virtual bool operator == (const nomme & ref) const { return xname == ref.xname; };
00180         virtual bool operator < (const nomme & ref) const { return xname < ref.xname; };
00181 
00182         const std::string & get_name() const { return xname; };
00183         void change_name(const std::string & x) { xname = x; };
00184         bool same_as(const nomme & ref) const { return xname == ref.xname; };
00185             // no need to have a virtual method, as signature will differ in inherited classes (argument type changes)
00186 
00187             // signature() is kept as an abstract method
00188             // clone() is abstract
00189 
00190 #ifdef LIBDAR_SPECIAL_ALLOC
00191         USE_SPECIAL_ALLOC(nomme);
00192 #endif
00193 
00194     protected:
00195         void inherited_dump(generic_file & f, bool small) const;
00196 
00197     private:
00198         std::string xname;
00199     };
00200 
00201 
00203     class inode : public nomme
00204     {
00205     public:
00206 
00208 
00209         enum comparison_fields
00210         {
00211             cf_all,          //< consider any available field for comparing inodes
00212             cf_ignore_owner, //< consider any available field except ownership fields
00213             cf_mtime,        //< consider any available field except ownership and permission fields
00214             cf_inode_type    //< only consider the file type
00215         };
00216 
00217         inode(const infinint & xuid, const infinint & xgid, U_16 xperm,
00218               const infinint & last_access,
00219               const infinint & last_modif,
00220               const infinint & last_change,
00221               const std::string & xname, const infinint & device);
00222         inode(user_interaction & dialog,
00223               generic_file & f,
00224               const archive_version & reading_ver,
00225               saved_status saved,
00226               generic_file *ea_loc,
00227               escape *ptr);      // if ptr is not NULL, reading a partial dump(), which was done with "small" set to true
00228         inode(const inode & ref);
00229         const inode & operator = (const inode & ref);
00230         ~inode();
00231 
00232         const infinint & get_uid() const { return uid; };
00233         const infinint & get_gid() const { return gid; };
00234         U_16 get_perm() const { return perm; };
00235         infinint get_last_access() const { return *last_acc; };
00236         infinint get_last_modif() const { return *last_mod; };
00237         void set_last_access(const infinint & x_time) { *last_acc = x_time; };
00238         void set_last_modif(const infinint & x_time) { *last_mod = x_time; };
00239         saved_status get_saved_status() const { return xsaved; };
00240         void set_saved_status(saved_status x) { xsaved = x; };
00241         infinint get_device() const { return *fs_dev; };
00242 
00243         bool same_as(const inode & ref) const;
00244         bool is_more_recent_than(const inode & ref, const infinint & hourshift) const;
00245             // used for RESTORATION
00246         virtual bool has_changed_since(const inode & ref, const infinint & hourshift, comparison_fields what_to_check) const;
00247             // signature() left as an abstract method
00248             // clone is abstract too
00249             // used for INCREMENTAL BACKUP
00250         void compare(const inode &other,
00251                      const mask & ea_mask,
00252                      comparison_fields what_to_check,
00253                      const infinint & hourshift,
00254                      bool symlink_date) const;
00255 
00256             // throw Erange exception if a difference has been detected
00257             // this is not a symetrical comparison, but all what is present
00258             // in the current object is compared against the argument
00259             // which may contain supplementary informations
00260             // used for DIFFERENCE
00261 
00262 
00263 
00265             // EXTENDED ATTRIBUTS Methods
00266             //
00267 
00268         enum ea_status { ea_none, ea_partial, ea_fake, ea_full, ea_removed };
00269             // ea_none    : no EA present for this inode in filesystem
00270             // ea_partial : EA present in filesystem but not stored (ctime used to check changes)
00271             // 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.
00272             // ea_full    : EA present in filesystem and attached to this inode
00273             // ea_removed : EA were present in the reference version, but not present anymore
00274 
00275             // I : to know whether EA data is present or not for this object
00276         void ea_set_saved_status(ea_status status);
00277         ea_status ea_get_saved_status() const { return ea_saved; };
00278 
00279             // II : to associate EA list to an inode object (mainly for backup operation) #EA_FULL only#
00280         void ea_attach(ea_attributs *ref);
00281         const ea_attributs *get_ea() const;              //   #<-- EA_FULL *and* EA_REMOVED# for this call only
00282         void ea_detach() const; //discards any future call to get_ea() !
00283         infinint ea_get_size() const; //returns the size of EA (still valid if ea have been detached)
00284 
00285             // III : to record where is dump the EA in the archive #EA_FULL only#
00286         void ea_set_offset(const infinint & pos) { *ea_offset = pos; };
00287         void ea_set_crc(const crc & val);
00288         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
00289         bool ea_get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument
00290 
00291             // IV : to know/record if EA have been modified # any EA status#
00292         infinint get_last_change() const;
00293         void set_last_change(const infinint & x_time);
00294         bool has_last_change() const { return last_cha != NULL; };
00295             // old format did provide last_change only when EA were present, since archive
00296             // format 8, this field is always present even in absence of EA. Thus it is
00297             // still necessary to check if the inode has a last_change() before
00298             // using get_last_change() (depends on the version of the archive read).
00299 
00300 
00301             // V : for archive migration (merging)
00302         void change_ea_location(generic_file *loc) { storage = loc; };
00303 
00305 
00306 #ifdef LIBDAR_SPECIAL_ALLOC
00307         USE_SPECIAL_ALLOC(inode);
00308 #endif
00309 
00310     protected:
00311         virtual void sub_compare(const inode & other) const {};
00312 
00314         escape *get_escape_layer() const { return esc; };
00315 
00316         void inherited_dump(generic_file & f, bool small) const;
00317 
00318     private :
00319         infinint uid;
00320         infinint gid;
00321         U_16 perm;
00322         infinint *last_acc, *last_mod;
00323         saved_status xsaved;
00324         ea_status ea_saved;
00325             //  the following is used only if ea_saved == full
00326         infinint *ea_offset;
00327         ea_attributs *ea;
00328         infinint ea_size;
00329             // the following is used if ea_saved == full or ea_saved == partial
00330         infinint *last_cha;
00331         crc *ea_crc;
00332         infinint *fs_dev;
00333         generic_file *storage; // where are stored EA
00334         archive_version edit;   // need to know EA format used in archive file
00335 
00336         escape *esc;  // if not NULL, the object is partially build from archive (at archive generation, dump() was called with small set to true)
00337 
00338         static const ea_attributs empty_ea;
00339     };
00340 
00342     class etoile
00343     {
00344     public:
00345 
00347 
00351         etoile(inode *host, const infinint & etiquette_number);
00352         etoile(const etoile & ref) { throw SRC_BUG; }; // copy constructor not allowed for this class
00353         const etoile & operator = (const etoile & ref) { throw SRC_BUG; }; // assignment not allowed for this class
00354         ~etoile() { delete hosted; };
00355 
00356         void add_ref(void *ref);
00357         void drop_ref(void *ref);
00358         infinint get_ref_count() const { return refs.size(); };
00359         inode *get_inode() const { return hosted; };
00360         infinint get_etiquette() const { return etiquette; };
00361         void change_etiquette(const infinint & new_val) { etiquette = new_val; };
00362 
00363 
00364         bool is_counted() const { return tags.counted; };
00365         bool is_wrote() const { return tags.wrote; };
00366         bool is_dumped() const { return tags.dumped; };
00367         void set_counted(bool val) { tags.counted = val ? 1 : 0; };
00368         void set_wrote(bool val) { tags.wrote = val ? 1 : 0; };
00369         void set_dumped(bool val) { tags.dumped = val ? 1 : 0; };
00370 
00371             // return the address of the first mirage that triggered the creation of this mirage
00372             // if this object is destroyed afterward this call returns NULL
00373         const void *get_first_ref() const { if(refs.size() == 0) throw SRC_BUG; return refs.front(); };
00374 
00375 #ifdef LIBDAR_SPECIAL_ALLOC
00376         USE_SPECIAL_ALLOC(etoile);
00377 #endif
00378 
00379     private:
00380         struct bool_tags
00381         {
00382             unsigned counted : 1; //< whether the inode has been counted
00383             unsigned wrote : 1;   //< whether the inode has its data copied to archive
00384             unsigned dumped : 1;  //< whether the inode information has been dumped in the catalogue
00385             unsigned : 5;         //< padding to get byte boundary and reserved for future use.
00386 
00387             bool_tags() { counted = wrote = dumped = 0; };
00388         };
00389 
00390         std::list<void *> refs; //< list of pointers to the mirages objects, in the order of their creation
00391         inode *hosted;
00392         infinint etiquette;
00393         bool_tags tags;
00394     };
00395 
00397 
00399     class mirage : public nomme
00400     {
00401     public:
00402         enum mirage_format {fmt_mirage,           //< new format
00403                             fmt_hard_link,        //< old dual format
00404                             fmt_file_etiquette }; //< old dual format
00405 
00406         mirage(const std::string & name, etoile *ref) : nomme(name) { star_ref = ref; if(ref == NULL) throw SRC_BUG; star_ref->add_ref(this); };
00407         mirage(user_interaction & dialog,
00408                generic_file & f,
00409                const archive_version & reading_ver,
00410                saved_status saved,
00411                entree_stats & stats,
00412                std::map <infinint, etoile *> & corres,
00413                compression default_algo,
00414                generic_file *data_loc,
00415                generic_file *ea_loc,
00416                mirage_format fmt,
00417                bool lax,
00418                escape *ptr);
00419         mirage(user_interaction & dialog,
00420                generic_file & f,
00421                const archive_version & reading_ver,
00422                saved_status saved,
00423                entree_stats & stats,
00424                std::map <infinint, etoile *> & corres,
00425                compression default_algo,
00426                generic_file *data_loc,
00427                generic_file *ea_loc,
00428                bool lax,
00429                escape *ptr);
00430         mirage(const mirage & ref) : nomme (ref) { star_ref = ref.star_ref; if(star_ref == NULL) throw SRC_BUG; star_ref->add_ref(this); };
00431         const mirage & operator = (const mirage & ref);
00432         ~mirage() { star_ref->drop_ref(this); };
00433 
00434         unsigned char signature() const { return 'm'; };
00435         entree *clone() const { return new (std::nothrow) mirage(*this); };
00436 
00437         inode *get_inode() const { if(star_ref == NULL) throw SRC_BUG; return star_ref->get_inode(); };
00438         infinint get_etiquette() const { return star_ref->get_etiquette(); };
00439         infinint get_etoile_ref_count() const { return star_ref->get_ref_count(); };
00440         etoile *get_etoile() const { return star_ref; };
00441 
00442         bool is_inode_counted() const { return star_ref->is_counted(); };
00443         bool is_inode_wrote() const { return star_ref->is_wrote(); };
00444         bool is_inode_dumped() const { return star_ref->is_dumped(); };
00445         void set_inode_counted(bool val) const { star_ref->set_counted(val); };
00446         void set_inode_wrote(bool val) const { star_ref->set_wrote(val); };
00447         void set_inode_dumped(bool val) const { star_ref->set_dumped(val); };
00448 
00449         void post_constructor(generic_file & f);
00450 
00452         bool is_first_mirage() const { return star_ref->get_first_ref() == this; };
00453 
00454 #ifdef LIBDAR_SPECIAL_ALLOC
00455         USE_SPECIAL_ALLOC(mirage);
00456 #endif
00457 
00458     protected:
00459         void inherited_dump(generic_file & f, bool small) const;
00460 
00461     private:
00462         etoile *star_ref;
00463 
00464         void init(user_interaction & dialog,
00465                   generic_file & f,
00466                   const archive_version & reading_ver,
00467                   saved_status saved,
00468                   entree_stats & stats,
00469                   std::map <infinint, etoile *> & corres,
00470                   compression default_algo,
00471                   generic_file *data_loc,
00472                   generic_file *ea_loc,
00473                   mirage_format fmt,
00474                   bool lax,
00475                   escape *ptr);
00476     };
00477 
00478 
00480     class file : public inode
00481     {
00482     public :
00483         enum get_data_mode
00484         {
00485             keep_compressed, //< provide access to compressed data
00486             keep_hole,       //< provide access to uncompressed data but sparse_file datastructure
00487             normal,          //< provide access to full data (uncompressed, uses skip() to restore holes)
00488             plain            //< provide access to plain data, no skip to restore holes, provide instead zeroed bytes
00489         };
00490 
00491         static const U_8 FILE_DATA_WITH_HOLE = 0x01; //< file's data contains hole datastructure
00492         static const U_8 FILE_DATA_IS_DIRTY = 0x02;  //< data modified while being saved
00493 
00494         file(const infinint & xuid, const infinint & xgid, U_16 xperm,
00495              const infinint & last_access,
00496              const infinint & last_modif,
00497              const infinint & last_change,
00498              const std::string & src,
00499              const path & che,
00500              const infinint & taille,
00501              const infinint & fs_device,
00502              bool x_furtive_read_mode);
00503         file(const file & ref);
00504         file(user_interaction & dialog,
00505              generic_file & f,
00506              const archive_version & reading_ver,
00507              saved_status saved,
00508              compression default_algo,
00509              generic_file *data_loc,
00510              generic_file *ea_loc,
00511              escape *ptr);
00512         ~file() { detruit(); };
00513 
00514         bool has_changed_since(const inode & ref, const infinint & hourshift, inode::comparison_fields what_to_check) const;
00515         infinint get_size() const { return *size; };
00516         void change_size(const infinint & s) const { *size = s; };
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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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 (std::nothrow) 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