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