Disk ARchive 2.4.2
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 // $Id: catalogue.hpp,v 1.111 2011/05/27 12:29:18 edrusb Rel $
00022 //
00023 /*********************************************************************/
00024 
00028 
00029 #ifndef CATALOGUE_HPP
00030 #define CATALOGUE_HPP
00031 
00032 #include "../my_config.h"
00033 
00034 extern "C"
00035 {
00036 #if HAVE_UNISTD_H
00037 #include <unistd.h>
00038 #endif
00039 } // end extern "C"
00040 
00041 #include <vector>
00042 #include <map>
00043 #include "infinint.hpp"
00044 #include "generic_file.hpp"
00045 #include "path.hpp"
00046 #include "header_version.hpp"
00047 #include "ea.hpp"
00048 #include "compressor.hpp"
00049 #include "integers.hpp"
00050 #include "mask.hpp"
00051 #include "special_alloc.hpp"
00052 #include "user_interaction.hpp"
00053 #include "label.hpp"
00054 #include "escape.hpp"
00055 
00056 namespace libdar
00057 {
00058     class etoile;
00059     class entree;
00060 
00063 
00064     enum saved_status
00065     {
00066         s_saved,      //< inode is saved in the archive
00067         s_fake,       //< inode is not saved in the archive but is in the archive of reference (isolation context) s_fake is no more used in archive format "08" and above: isolated catalogue do keep the data pointers and s_saved stays a valid status in isolated catalogues.
00068         s_not_saved   //< inode is not saved in the archive
00069     };
00070 
00072     struct entree_stats
00073     {
00074         infinint num_x;                  //< number of file referenced as destroyed since last backup
00075         infinint num_d;                  //< number of directories
00076         infinint num_f;                  //< number of plain files (hard link or not, thus file directory entries)
00077         infinint num_c;                  //< number of char devices
00078         infinint num_b;                  //< number of block devices
00079         infinint num_p;                  //< number of named pipes
00080         infinint num_s;                  //< number of unix sockets
00081         infinint num_l;                  //< number of symbolic links
00082         infinint num_D;                  //< number of Door
00083         infinint num_hard_linked_inodes; //< number of inode that have more than one link (inode with "hard links")
00084         infinint num_hard_link_entries;  //< total number of hard links (file directory entry pointing to \an
00085             //< inode already linked in the same or another directory (i.e. hard linked))
00086         infinint saved; //< total number of saved inode (unix inode, not inode class) hard links do not count here
00087         infinint total; //< total number of inode in archive (unix inode, not inode class) hard links do not count here
00088         void clear() { num_x = num_d = num_f = num_c = num_b = num_p
00089                 = num_s = num_l = num_D = num_hard_linked_inodes
00090                 = num_hard_link_entries = saved = total = 0; };
00091         void add(const entree *ref);
00092         void listing(user_interaction & dialog) const;
00093     };
00094 
00096     class entree
00097     {
00098     public :
00099         static entree *read(user_interaction & dialog,
00100                             generic_file & f, const archive_version & reading_ver,
00101                             entree_stats & stats,
00102                             std::map <infinint, etoile *> & corres,
00103                             compression default_algo,
00104                             generic_file *data_loc,
00105                             generic_file *ea_loc,
00106                             bool lax,
00107                             bool only_detruit,
00108                             escape *ptr);
00109 
00110         virtual ~entree() {};
00111 
00113 
00120         void dump(generic_file & f, bool small) const;
00121 
00123 
00130         void specific_dump(generic_file & f, bool small) const { inherited_dump(f, small); };
00131 
00133 
00136         virtual void post_constructor(generic_file & f) {};
00137 
00138 
00139         virtual unsigned char signature() const = 0;
00140         virtual entree *clone() const = 0;
00141 
00142             // SPECIAL ALLOC not adapted here
00143             // because some inherited class object (eod) are
00144             // temporary
00145 
00146     protected:
00147         virtual void inherited_dump(generic_file & f, bool small) const;
00148 
00149 
00150     private:
00151         static const U_I ENTREE_CRC_SIZE;
00152 
00153     };
00154 
00155     extern bool compatible_signature(unsigned char a, unsigned char b);
00156     extern unsigned char mk_signature(unsigned char base, saved_status state);
00157 
00159     class eod : public entree
00160     {
00161     public :
00162         eod() {};
00163         eod(generic_file & f) {};
00164             // dump defined by entree
00165         unsigned char signature() const { return 'z'; };
00166         entree *clone() const { return new eod(); };
00167 
00168             // eod are generally temporary object they are NOT
00169             // well adapted to "SPECIAL ALLOC"
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) { crc::set_crc_pointer(ea_crc, &val); };
00287         void ea_get_crc(crc & val) const;
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 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         infinint get_storage_size() const { return *storage_size; };
00516         void set_storage_size(const infinint & s) { *storage_size = s; };
00517         virtual generic_file *get_data(get_data_mode mode) const; // returns a newly allocated object in read_only mode
00518         void clean_data(); // partially free memory (but get_data() becomes disabled)
00519         void set_offset(const infinint & r);
00520         const infinint & get_offset() const;
00521         unsigned char signature() const { return mk_signature('f', get_saved_status()); };
00522 
00523         void set_crc(const crc &c) { crc::set_crc_pointer(check, &c); };
00524         bool get_crc(crc & c) const;
00525         bool has_crc() const { return check != NULL; };
00526         bool get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument
00527         void drop_crc() { if(check != NULL) { delete check; check = NULL; } };
00528 
00529             // whether the plain file has to detect sparse file
00530         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; };
00531 
00532         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; };
00533 
00534             // whether the plain file is stored with a sparse_file datastructure in the archive
00535         bool get_sparse_file_detection_read() const { return (file_data_status_read & FILE_DATA_WITH_HOLE) != 0; };
00536         bool get_sparse_file_detection_write() const { return (file_data_status_write & FILE_DATA_WITH_HOLE) != 0; };
00537 
00538         entree *clone() const { return new file(*this); };
00539 
00540         compression get_compression_algo_read() const { return algo_read; };
00541 
00542         compression get_compression_algo_write() const { return algo_write; };
00543 
00544             // object migration methods (merging)
00545         void change_compression_algo_write(compression x) { algo_write = x; };
00546         void change_location(generic_file *x) { loc = x; };
00547 
00548             // dirtiness
00549 
00550         bool is_dirty() const { return dirty; };
00551         void set_dirty(bool value) { dirty = value; };
00552 
00553 #ifdef LIBDAR_SPECIAL_ALLOC
00554         USE_SPECIAL_ALLOC(file);
00555 #endif
00556 
00557     protected:
00558         void sub_compare(const inode & other) const;
00559         void inherited_dump(generic_file & f, bool small) const;
00560         void post_constructor(generic_file & f);
00561 
00562         enum { empty, from_path, from_cat } status;
00563 
00564     private:
00565         std::string chemin;     //< path to the data (when read from filesystem)
00566         infinint *offset;       //< start location of the data in 'loc'
00567         infinint *size;         //< size of the data (uncompressed)
00568         infinint *storage_size; //< how much data used in archive (after compression)
00569         crc *check;
00570         bool dirty;     //< true when a file has been modified at the time it was saved
00571 
00572         generic_file *loc;      //< where to find data (eventually compressed) at the recorded offset and for storage_size length
00573         compression algo_read;  //< which compression algorithm to use to read the file's data
00574         compression algo_write; //< which compression algorithm to use to write down (merging) the file's data
00575         bool furtive_read_mode; // used only when status equals "from_path"
00576         char file_data_status_read; // defines the datastructure to use when reading the data
00577         char file_data_status_write; // defines the datastructure to apply when writing down the data
00578 
00579         void detruit();
00580     };
00581 
00583     class door : public file
00584     {
00585     public:
00586         door(const infinint & xuid, const infinint & xgid, U_16 xperm,
00587              const infinint & last_access,
00588              const infinint & last_modif,
00589              const infinint & last_change,
00590              const std::string & src,
00591              const path & che,
00592              const infinint & fs_device) : file(xuid, xgid, xperm, last_access, last_modif,
00593                                                 last_change, src, che, 0, fs_device, false) {};
00594         door(user_interaction & dialog,
00595              generic_file & f,
00596              const archive_version & reading_ver,
00597              saved_status saved,
00598              compression default_algo,
00599              generic_file *data_loc,
00600              generic_file *ea_loc,
00601              escape *ptr) : file(dialog, f, reading_ver, saved, default_algo, data_loc, ea_loc, ptr) {};
00602 
00603         unsigned char signature() const { return mk_signature('o', get_saved_status()); };
00604 
00605         generic_file *get_data(get_data_mode mode) const; // inherited from class file
00606     };
00607 
00609     class lien : public inode
00610     {
00611     public :
00612         lien(const infinint & uid, const infinint & gid, U_16 perm,
00613              const infinint & last_access,
00614              const infinint & last_modif,
00615              const infinint & last_change,
00616              const std::string & name,
00617              const std::string & target,
00618              const infinint & fs_device);
00619         lien(user_interaction & dialog,
00620              generic_file & f,
00621              const archive_version & reading_ver,
00622              saved_status saved,
00623              generic_file *ea_loc,
00624              escape *ptr);
00625 
00626         const std::string & get_target() const;
00627         void set_target(std::string x);
00628 
00629             // using the method is_more_recent_than() from inode
00630             // using method has_changed_since() from inode class
00631         unsigned char signature() const { return mk_signature('l', get_saved_status()); };
00632         entree *clone() const { return new lien(*this); };
00633 
00634 #ifdef LIBDAR_SPECIAL_ALLOC
00635         USE_SPECIAL_ALLOC(lien);
00636 #endif
00637     protected :
00638         void sub_compare(const inode & other) const;
00639         void inherited_dump(generic_file & f, bool small) const;
00640 
00641 
00642     private :
00643         std::string points_to;
00644     };
00645 
00647     class directory : public inode
00648     {
00649     public :
00650         directory(const infinint & xuid, const infinint & xgid, U_16 xperm,
00651                   const infinint & last_access,
00652                   const infinint & last_modif,
00653                   const infinint & last_change,
00654                   const std::string & xname,
00655                   const infinint & device);
00656         directory(const directory &ref); // only the inode part is build, no children is duplicated (empty dir)
00657         const directory & operator = (const directory & ref); // set the inode part *only* no subdirectories/subfiles are copies or removed.
00658         directory(user_interaction & dialog,
00659                   generic_file & f,
00660                   const archive_version & reading_ver,
00661                   saved_status saved,
00662                   entree_stats & stats,
00663                   std::map <infinint, etoile *> & corres,
00664                   compression default_algo,
00665                   generic_file *data_loc,
00666                   generic_file *ea_loc,
00667                   bool lax,
00668                   bool only_detruit, // objects of other class than detruit and directory are not built in memory
00669                   escape *ptr);
00670         ~directory(); // detruit aussi tous les fils et se supprime de son 'parent'
00671 
00672         void add_children(nomme *r); // when r is a directory, 'parent' is set to 'this'
00673         bool has_children() const { return !fils.empty(); };
00674         void reset_read_children() const;
00675         void end_read() const;
00676         bool read_children(const nomme * &r) const; // read the direct children of the directory, returns false if no more is available
00677             // remove all entry not yet read by read_children
00678         void tail_to_read_children();
00679 
00680         void remove(const std::string & name); // remove the given entry from the catalogue
00681             // as side effect the reset_read_children() method must be called.
00682 
00683         directory * get_parent() const { return parent; };
00684         bool search_children(const std::string &name, nomme *&ref);
00685         bool callback_for_children_of(user_interaction & dialog, const std::string & sdir, bool isolated = false) const;
00686 
00687             // using is_more_recent_than() from inode class
00688             // using method has_changed_since() from inode class
00689         unsigned char signature() const { return mk_signature('d', get_saved_status()); };
00690 
00691             // some data has changed since archive of reference in this directory or subdirectories
00692         bool get_recursive_has_changed() const { return recursive_has_changed; };
00693             // update the recursive_has_changed field
00694         void recursive_has_changed_update() const;
00695 
00696             // get then number of "nomme" entry contained in this directory and subdirectories (recursive call)
00697         infinint get_tree_size() const;
00698             // get the number of entry having some EA set in the directory tree (recursive call)
00699         infinint get_tree_ea_num() const;
00700             // get the number of entry that are hard linked inode (aka mirage in dar implementation) (recursive call)
00701         infinint get_tree_mirage_num() const;
00702             // for each mirage found (hard link implementation) in the directory tree, add its etiquette to the returned
00703             // list with the number of reference that has been found in the tree. (map[etiquette] = number of occurence)
00704             // from outside of class directory, the given argument is expected to be an empty map.
00705         void get_etiquettes_found_in_tree(std::map<infinint, infinint> & already_found) const;
00706 
00707             // whether this directory is empty or not
00708         bool is_empty() const { return fils.empty(); };
00709 
00710             // recursively remove all mirage entries
00711         void remove_all_mirages_and_reduce_dirs();
00712 
00713         entree *clone() const { return new directory(*this); };
00714 
00715 #ifdef LIBDAR_SPECIAL_ALLOC
00716         USE_SPECIAL_ALLOC(directory);
00717 #endif
00718 
00719     protected:
00720         void inherited_dump(generic_file & f, bool small) const;
00721 
00722     private :
00723         static const eod fin;
00724 
00725         directory *parent;
00726         std::map<std::string, nomme *> fils; // used for fast lookup
00727         std::list<nomme *> ordered_fils;
00728         std::list<nomme *>::iterator it;
00729         bool recursive_has_changed;
00730 
00731         void clear();
00732     };
00733 
00735     class device : public inode
00736     {
00737     public :
00738         device(const infinint & uid, const infinint & gid, U_16 perm,
00739                const infinint & last_access,
00740                const infinint & last_modif,
00741                const infinint &last_change,
00742                const std::string & name,
00743                U_16 major,
00744                U_16 minor,
00745                const infinint & fs_device);
00746         device(user_interaction & dialog,
00747                generic_file & f,
00748                const archive_version & reading_ver,
00749                saved_status saved,
00750                generic_file *ea_loc,
00751                escape *ptr);
00752 
00753         int get_major() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xmajor; };
00754         int get_minor() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xminor; };
00755         void set_major(int x) { xmajor = x; };
00756         void set_minor(int x) { xminor = x; };
00757 
00758             // using method is_more_recent_than() from inode class
00759             // using method has_changed_since() from inode class
00760             // signature is left pure abstract
00761 
00762 #ifdef LIBDAR_SPECIAL_ALLOC
00763         USE_SPECIAL_ALLOC(device);
00764 #endif
00765 
00766     protected :
00767         void sub_compare(const inode & other) const;
00768         void inherited_dump(generic_file & f, bool small) const;
00769 
00770     private :
00771         U_16 xmajor, xminor;
00772     };
00773 
00775     class chardev : public device
00776     {
00777     public:
00778         chardev(const infinint & uid, const infinint & gid, U_16 perm,
00779                 const infinint & last_access,
00780                 const infinint & last_modif,
00781                 const infinint & last_change,
00782                 const std::string & name,
00783                 U_16 major,
00784                 U_16 minor,
00785                 const infinint & fs_device) : device(uid, gid, perm,
00786                                                      last_access,
00787                                                      last_modif,
00788                                                      last_change,
00789                                                      name,
00790                                                      major, minor, fs_device) {};
00791         chardev(user_interaction & dialog,
00792                 generic_file & f,
00793                 const archive_version & reading_ver,
00794                 saved_status saved,
00795                 generic_file *ea_loc,
00796                 escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00797 
00798             // using dump from device class
00799             // using method is_more_recent_than() from device class
00800             // using method has_changed_since() from device class
00801         unsigned char signature() const { return mk_signature('c', get_saved_status()); };
00802         entree *clone() const { return new chardev(*this); };
00803 
00804 #ifdef LIBDAR_SPECIAL_ALLOC
00805         USE_SPECIAL_ALLOC(chardev);
00806 #endif
00807     };
00808 
00810     class blockdev : public device
00811     {
00812     public:
00813         blockdev(const infinint & uid, const infinint & gid, U_16 perm,
00814                  const infinint & last_access,
00815                  const infinint & last_modif,
00816                  const infinint & last_change,
00817                  const std::string & name,
00818                  U_16 major,
00819                  U_16 minor,
00820                  const infinint & fs_device) : device(uid, gid, perm, last_access,
00821                                                       last_modif, last_change, name,
00822                                                       major, minor, fs_device) {};
00823         blockdev(user_interaction & dialog,
00824                  generic_file & f,
00825                  const archive_version & reading_ver,
00826                  saved_status saved,
00827                  generic_file *ea_loc,
00828                  escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00829 
00830             // using dump from device class
00831             // using method is_more_recent_than() from device class
00832             // using method has_changed_since() from device class
00833         unsigned char signature() const { return mk_signature('b', get_saved_status()); };
00834         entree *clone() const { return new blockdev(*this); };
00835 
00836 #ifdef LIBDAR_SPECIAL_ALLOC
00837         USE_SPECIAL_ALLOC(blockdev);
00838 #endif
00839     };
00840 
00842     class tube : public inode
00843     {
00844     public :
00845         tube(const infinint & xuid, const infinint & xgid, U_16 xperm,
00846              const infinint & last_access,
00847              const infinint & last_modif,
00848              const infinint & last_change,
00849              const std::string & xname,
00850              const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); };
00851         tube(user_interaction & dialog,
00852              generic_file & f,
00853              const archive_version & reading_ver,
00854              saved_status saved,
00855              generic_file *ea_loc,
00856              escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00857 
00858             // using dump from inode class
00859             // using method is_more_recent_than() from inode class
00860             // using method has_changed_since() from inode class
00861         unsigned char signature() const { return mk_signature('p', get_saved_status()); };
00862         entree *clone() const { return new tube(*this); };
00863 
00864 #ifdef LIBDAR_SPECIAL_ALLOC
00865         USE_SPECIAL_ALLOC(tube);
00866 #endif
00867     };
00868 
00870     class prise : public inode
00871     {
00872     public :
00873         prise(const infinint & xuid, const infinint & xgid, U_16 xperm,
00874               const infinint & last_access,
00875               const infinint & last_modif,
00876               const infinint & last_change,
00877               const std::string & xname,
00878               const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); };
00879         prise(user_interaction & dialog,
00880               generic_file & f,
00881               const archive_version & reading_ver,
00882               saved_status saved,
00883               generic_file *ea_loc,
00884               escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {};
00885 
00886             // using dump from inode class
00887             // using method is_more_recent_than() from inode class
00888             // using method has_changed_since() from inode class
00889         unsigned char signature() const { return mk_signature('s', get_saved_status()); };
00890         entree *clone() const { return new prise(*this); };
00891 
00892 #ifdef LIBDAR_SPECIAL_ALLOC
00893         USE_SPECIAL_ALLOC(prise);
00894 #endif
00895     };
00896 
00898     class detruit : public nomme
00899     {
00900     public :
00901         detruit(const std::string & name, unsigned char firm, const infinint & date) : nomme(name) , del_date(date) { signe = firm; };
00902         detruit(generic_file & f, const archive_version & reading_ver);
00903         detruit(const nomme &ref) : nomme(ref.get_name()), del_date(0) { signe = ref.signature(); };
00904 
00905         unsigned char get_signature() const { return signe; };
00906         void set_signature(unsigned char x) { signe = x; };
00907         unsigned char signature() const { return 'x'; };
00908         entree *clone() const { return new detruit(*this); };
00909 
00910         const infinint & get_date() const { return del_date; };
00911         void set_date(const infinint & ref) { del_date = ref; };
00912 
00913 #ifdef LIBDAR_SPECIAL_ALLOC
00914         USE_SPECIAL_ALLOC(detruit);
00915 #endif
00916     protected:
00917         void inherited_dump(generic_file & f, bool small) const;
00918 
00919     private :
00920         unsigned char signe;
00921         infinint del_date;
00922     };
00923 
00925     class ignored : public nomme
00926     {
00927     public :
00928         ignored(const std::string & name) : nomme(name) {};
00929         ignored(generic_file & f) : nomme(f) { throw SRC_BUG; };
00930 
00931         unsigned char signature() const { return 'i'; };
00932         entree *clone() const { return new ignored(*this); };
00933 #ifdef LIBDAR_SPECIAL_ALLOC
00934         USE_SPECIAL_ALLOC(ignored);
00935 #endif
00936 
00937     protected:
00938         void inherited_dump(generic_file & f, bool small) const { throw SRC_BUG; };
00939 
00940     };
00941 
00943     class ignored_dir : public inode
00944     {
00945     public:
00946         ignored_dir(const directory &target) : inode(target) {};
00947         ignored_dir(user_interaction & dialog,
00948                     generic_file & f,
00949                     const archive_version & reading_ver,
00950                     generic_file *ea_loc,
00951                     escape *ptr) : inode(dialog, f, reading_ver, s_not_saved, ea_loc, ptr) { throw SRC_BUG; };
00952 
00953         unsigned char signature() const { return 'j'; };
00954         entree *clone() const { return new ignored_dir(*this); };
00955 #ifdef LIBDAR_SPECIAL_ALLOC
00956         USE_SPECIAL_ALLOC(ignored_dir);
00957 #endif
00958 
00959     protected:
00960         void inherited_dump(generic_file & f, bool small) const; // behaves like an empty directory
00961 
00962     };
00963 
00965     class catalogue : protected mem_ui
00966     {
00967     public :
00968         catalogue(user_interaction & dialog,
00969                   const infinint & root_last_modif,
00970                   const label & data_name);
00971         catalogue(user_interaction & dialog,
00972                   generic_file & f,
00973                   const archive_version & reading_ver,
00974                   compression default_algo,
00975                   generic_file *data_loc,
00976                   generic_file *ea_loc,
00977                   bool lax,
00978                   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
00979                   bool only_detruit = false); //< if set to true, only directories and detruit objects are read from the archive
00980         catalogue(const catalogue & ref) : mem_ui(ref), out_compare(ref.out_compare) { partial_copy_from(ref); };
00981         const catalogue & operator = (const catalogue &ref);
00982         virtual ~catalogue() { detruire(); };
00983 
00984 
00985             // reading methods. The reading is iterative and uses the current_read directory pointer
00986 
00987         virtual void reset_read() const; // set the reading cursor to the beginning of the catalogue
00988         virtual void end_read() const; // set the reading cursor to the end of the catalogue
00989         virtual void skip_read_to_parent_dir() const;
00990             // skip all items of the current dir and of any subdir, the next call will return
00991             // next item of the parent dir (no eod to exit from the current dir !)
00992         virtual bool read(const entree * & ref) const;
00993             // sequential read (generates eod) and return false when all files have been read
00994         virtual bool read_if_present(std::string *name, const nomme * & ref) const;
00995             // pseudo-sequential read (reading a directory still
00996             // implies that following read are located in this subdirectory up to the next EOD) but
00997             // it returns false if no entry of this name are present in the current directory
00998             // a call with NULL as first argument means to set the current dir the parent directory
00999         void remove_read_entry(std::string & name);
01000             // in the currently read directory, removes the entry which name is given in argument
01001         const directory & get_current_reading_dir() const { return *current_read; };
01002             // remove from the catalogue all the entries that have not yet been read
01003             // by read().
01004         void tail_catalogue_to_current_read();
01005 
01006 
01007         void reset_sub_read(const path &sub); // initialise sub_read to the given directory
01008         bool sub_read(const entree * &ref); // sequential read of the catalogue, ignoring all that
01009             // is not part of the subdirectory specified with reset_sub_read
01010             // the read include the inode leading to the sub_tree as well as the pending eod
01011 
01012             // return true if the last read entry has already been read
01013             // and has not to be counted again. This is never the case for catalogue but may occure
01014             // with escape_catalogue (where from the 'virtual').
01015             // last this method gives a valid result only if the last read() entry is a directory as
01016             // only directory may be read() twice.
01017         virtual bool read_second_time_dir() const { return false; };
01018 
01019 
01020             // Additions methods. The addition is also iterative but uses its specific current_add directory pointer
01021 
01022         void reset_add();
01023 
01025             // real implementation is only needed in escape_catalogue class, here there nothing to be done
01026         virtual void pre_add(const entree *ref, compressor *compr) const {};
01027         virtual void pre_add_ea(const entree *ref, compressor *compr) const {};
01028         virtual void pre_add_crc(const entree *ref, compressor *compr) const {};
01029         virtual void pre_add_dirty(compressor *compr) const {};
01030         virtual void pre_add_ea_crc(const entree *ref, compressor *compr) const {};
01031         virtual void pre_add_waste_mark(compressor *compr) const {};
01032         virtual void pre_add_failed_mark(compressor *compr) const {};
01033         virtual escape *get_escape_layer() const { return NULL; };
01034 
01035         void add(entree *ref); // add at end of catalogue (sequential point of view)
01036         void re_add_in(const std::string &subdirname); // return into an already existing subdirectory for further addition
01037         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
01038         void add_in_current_read(nomme *ref); // add in currently read directory
01039 
01040 
01041 
01042             // Comparison methods. The comparision is here also iterative and uses its specific current_compare directory pointer
01043 
01044         void reset_compare();
01045         bool compare(const entree * name, const entree * & extracted);
01046             // returns true if the ref exists, and gives it back in second argument as it is in the current catalogue.
01047             // returns false is no entry of that nature exists in the catalogue (in the current directory)
01048             // if ref is a directory, the operation is normaly relative to the directory itself, but
01049             // such a call implies a chdir to that directory. thus, a call with an EOD is necessary to
01050             // change to the parent directory.
01051             // note :
01052             // if a directory is not present, returns false, but records the inexistant subdirectory
01053             // structure defined by the following calls to this routine, this to be able to know when
01054             // the last available directory is back the current one when changing to parent directory,
01055             // and then proceed with normal comparison of inode. In this laps of time, the call will
01056             // always return false, while it temporary stores the missing directory structure
01057 
01058 
01059 
01060             // non interative methods
01061 
01062         bool direct_read(const path & ref, const nomme * &ret);
01063         infinint update_destroyed_with(catalogue & ref);
01064             // ref must have the same root, else the operation generates an exception
01065 
01066         void update_absent_with(catalogue & ref, infinint aborting_next_etoile);
01067             // in case of abortion, completes missing files as if what could not be
01068             // inspected had not changed since the reference was done
01069             // aborting_last_etoile is the highest etoile reference withing "this" current object.
01070 
01071         void dump(generic_file & f) const;
01072         void listing(bool isolated,
01073                      const mask &selection,
01074                      const mask & subtree,
01075                      bool filter_unsaved,
01076                      bool list_ea,
01077                      std::string marge) const;
01078         void tar_listing(bool isolated,
01079                          const mask & selection,
01080                          const mask & subtree,
01081                          bool filter_unsaved,
01082                          bool list_ea,
01083                          std::string beginning) const;
01084         void xml_listing(bool isolated,
01085                          const mask & selection,
01086                          const mask & subtree,
01087                          bool filter_unsaved,
01088                          bool list_ea,
01089                          std::string beginning) const;
01090 
01091         entree_stats get_stats() const { return stats; };
01092 
01094         bool is_empty() const { if(contenu == NULL) throw SRC_BUG; return contenu->is_empty(); };
01095 
01096         const directory *get_contenu() const { return contenu; }; // used by data_tree
01097 
01098         const label & get_data_name() const { return ref_data_name; };
01099         infinint get_root_dir_last_modif() const { return contenu->get_last_modif(); };
01100 
01102         void launch_recursive_has_changed_update() const { contenu->recursive_has_changed_update(); };
01103 
01104         infinint get_root_mtime() const { return contenu->get_last_modif(); };
01105 
01107         void reset_all();
01108 
01109 #ifdef LIBDAR_SPECIAL_ALLOC
01110         USE_SPECIAL_ALLOC(catalogue);
01111 #endif
01112 
01113     protected:
01114         entree_stats & access_stats() { return stats; };
01115         void set_data_name(const label & val) { ref_data_name = val; };
01116         void copy_detruits_from(const catalogue & ref); // needed for escape_catalogue implementation only.
01117 
01118         const eod * get_r_eod_address() const { return & r_eod; }; // eod are never stored in the catalogue
01119             // however it is sometimes required to return such a reference to a valid object
01120             // owned by the catalogue.
01121 
01122 
01125         void swap_stuff(catalogue & ref);
01126 
01127     private :
01128         directory *contenu;               
01129         path out_compare;                 
01130         directory *current_compare;       
01131         directory *current_add;           
01132         directory *current_read;          
01133         path *sub_tree;                   
01134         signed int sub_count;             
01135         entree_stats stats;               
01136         label ref_data_name;              
01137 
01138         void partial_copy_from(const catalogue &ref);
01139         void detruire();
01140 
01141         static const eod r_eod;           // needed to return eod reference, without taking risk of saturating memory
01142         static const U_I CAT_CRC_SIZE;
01143     };
01144 
01145 
01146 
01148 
01149 } // end of namespace
01150 
01151 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines