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