diff --git a/encfs/FileUtils.cpp b/encfs/FileUtils.cpp index d16ffb7..e9cdaaf 100644 --- a/encfs/FileUtils.cpp +++ b/encfs/FileUtils.cpp @@ -57,6 +57,7 @@ #include "i18n.h" +#include #include #include #include @@ -96,7 +97,8 @@ static int V5SubVersionDefault = 0; // 20080813 was really made on 20080413 -- typo on date.. //const int V6SubVersion = 20080813; // switch to v6/XML, add allowHoles option -const int V6SubVersion = 20080816; // add salt and iteration count +//const int V6SubVersion = 20080816; // add salt and iteration count +const int V6SubVersion = 20100713; // add version field for boost 1.42+ struct ConfigInfo { @@ -122,6 +124,8 @@ struct ConfigInfo {NULL,Config_None, NULL, NULL, NULL, 0, 0}}; +#include "boost-versioning.h" + // define serialization helpers namespace boost { @@ -132,6 +136,9 @@ namespace boost unsigned int version) { (void)version; + // version 20 (aka 20100613) + ar << make_nvp("version", cfg.subVersion); + ar << make_nvp("creator", cfg.creator); ar << make_nvp("cipherAlg", cfg.cipherIface); ar << make_nvp("nameAlg", cfg.nameIface); @@ -161,7 +168,30 @@ namespace boost template void load(Archive &ar, EncFSConfig &cfg, unsigned int version) { - cfg.subVersion = version; + rInfo("version = %i", version); + // TODO: figure out how to deprecate all but the first case.. + if (version == 20 || version >= 20100713) + { + rInfo("found new serialization format"); + ar >> make_nvp("version", cfg.subVersion); + } else if (version == 26800) + { + rInfo("found 20080816 version"); + cfg.subVersion = 20080816; + } else if (version == 26797) + { + rInfo("found 20080813"); + cfg.subVersion = 20080813; + } else if (version < (unsigned int)V5SubVersion) + { + rError("Invalid version - please fix config file"); + } else + { + rInfo("Boost <= 1.41 compatibility mode"); + cfg.subVersion = version; + } + rInfo("subVersion = %i", cfg.subVersion); + ar >> make_nvp("creator", cfg.creator); ar >> make_nvp("cipherAlg", cfg.cipherIface); ar >> make_nvp("nameAlg", cfg.nameIface); @@ -184,7 +214,7 @@ namespace boost cfg.assignKeyData(key, encodedSize); delete[] key; - if(version >= 20080816) + if(cfg.subVersion >= 20080816) { int saltLen; ar >> make_nvp("saltLen", saltLen); @@ -220,8 +250,6 @@ namespace boost } } } -BOOST_CLASS_VERSION(EncFSConfig, V6SubVersion) - EncFS_Root::EncFS_Root() { diff --git a/encfs/boost-versioning.h b/encfs/boost-versioning.h new file mode 100644 index 0000000..b3cfa51 --- /dev/null +++ b/encfs/boost-versioning.h @@ -0,0 +1,96 @@ +#ifndef BOOST_VERSIONING_INCL +#define BOOST_VERSIONING_INCL + +// This header stores workaround code for dealing with incompatible changes +// made to boost archive/serialization classes. + + +#if (BOOST_VERSION <= 104100) +// Easy case, boost archive serial numbers are sizeof(int) +BOOST_CLASS_VERSION(EncFSConfig, V6SubVersion) +#else +// starting with boost 1.42, serial numbers change to 8-bit. However to make +// things tricker, the internal comparison is more like 16bit, which makes +// writing backward compatible code very tricky. + +// We make a partial specialization of the iserializer class to remove the +// version number checking which would otherwise cause boost::serialization to +// throw an exception if it came across a version that was greater then what +// we specify in BOOST_CLASS_VERSION below. Without this, manual editing +// of the file is needed before boost will allow us to read it. + +// See bug http://code.google.com/p/encfs/issues/detail?id=60 + +BOOST_CLASS_VERSION(EncFSConfig, 20) + + +namespace boost { +namespace archive { +namespace detail { + + +// Specialize iserializer class in order to get rid of version check +template +class iserializer : public basic_iserializer +{ +private: + virtual void destroy(/*const*/ void *address) const { + boost::serialization::access::destroy(static_cast(address)); + } +protected: + explicit iserializer() : + basic_iserializer( + boost::serialization::singleton< + BOOST_DEDUCED_TYPENAME + boost::serialization::type_info_implementation::type + >::get_const_instance() + ) + {} +public: + virtual BOOST_DLLEXPORT void load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version + ) const BOOST_USED; + virtual bool class_info() const { + return boost::serialization::implementation_level::value + >= boost::serialization::object_class_info; + } + virtual bool tracking(const unsigned int /* flags */) const { + return boost::serialization::tracking_level::value + == boost::serialization::track_always + || ( boost::serialization::tracking_level::value + == boost::serialization::track_selectively + && serialized_as_pointer()); + } + virtual version_type version() const { + return version_type(::boost::serialization::version::value); + } + virtual bool is_polymorphic() const { + return boost::is_polymorphic::value; + } + virtual ~iserializer(){}; +}; + +template +BOOST_DLLEXPORT void iserializer::load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version +) const { + boost::serialization::serialize_adl( + boost::serialization::smart_cast_reference(ar), + * static_cast(x), + file_version + ); +} + +} +} +} + +#endif + + + +#endif // BOOST_VERSIONING_INCL