add boost 1.42+ support w/ backward compatibility

git-svn-id: http://encfs.googlecode.com/svn/trunk@55 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
Valient Gough 2010-06-15 06:20:51 +00:00
parent 42d8ce30cd
commit 47e0c24182
2 changed files with 129 additions and 5 deletions

View File

@ -57,6 +57,7 @@
#include "i18n.h"
#include <boost/version.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
@ -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<class Archive>
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()
{

96
encfs/boost-versioning.h Normal file
View File

@ -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 Archive>
class iserializer<Archive, EncFSConfig> : public basic_iserializer
{
private:
virtual void destroy(/*const*/ void *address) const {
boost::serialization::access::destroy(static_cast<EncFSConfig *>(address));
}
protected:
explicit iserializer() :
basic_iserializer(
boost::serialization::singleton<
BOOST_DEDUCED_TYPENAME
boost::serialization::type_info_implementation<EncFSConfig>::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<EncFSConfig>::value
>= boost::serialization::object_class_info;
}
virtual bool tracking(const unsigned int /* flags */) const {
return boost::serialization::tracking_level<EncFSConfig>::value
== boost::serialization::track_always
|| ( boost::serialization::tracking_level<EncFSConfig>::value
== boost::serialization::track_selectively
&& serialized_as_pointer());
}
virtual version_type version() const {
return version_type(::boost::serialization::version<EncFSConfig>::value);
}
virtual bool is_polymorphic() const {
return boost::is_polymorphic<EncFSConfig>::value;
}
virtual ~iserializer(){};
};
template<class Archive>
BOOST_DLLEXPORT void iserializer<Archive, EncFSConfig>::load_object_data(
basic_iarchive & ar,
void *x,
const unsigned int file_version
) const {
boost::serialization::serialize_adl(
boost::serialization::smart_cast_reference<Archive &>(ar),
* static_cast<EncFSConfig *>(x),
file_version
);
}
}
}
}
#endif
#endif // BOOST_VERSIONING_INCL