mirror of
https://github.com/vgough/encfs.git
synced 2024-11-29 03:15:07 +01:00
7799c88df6
git-svn-id: http://encfs.googlecode.com/svn/trunk@93 db9cf616-1c43-0410-9cb8-a902689de0d6
257 lines
5.3 KiB
C++
257 lines
5.3 KiB
C++
/*****************************************************************************
|
|
* Author: Valient Gough <vgough@pobox.com>
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (c) 2004, Valient Gough
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by the
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "base/ConfigVar.h"
|
|
#include "base/Error.h"
|
|
|
|
#include <glog/logging.h>
|
|
#include <cstring>
|
|
|
|
namespace encfs {
|
|
|
|
#ifndef MIN
|
|
inline int MIN(int a, int b)
|
|
{
|
|
return (a < b) ? a : b;
|
|
}
|
|
#endif
|
|
|
|
|
|
ConfigVar::ConfigVar()
|
|
: pd( new ConfigVarData )
|
|
{
|
|
pd->offset = 0;
|
|
}
|
|
|
|
ConfigVar::ConfigVar(const std::string &buf)
|
|
: pd( new ConfigVarData )
|
|
{
|
|
pd->buffer = buf;
|
|
pd->offset = 0;
|
|
}
|
|
|
|
ConfigVar::ConfigVar(const ConfigVar &src)
|
|
{
|
|
pd = src.pd;
|
|
}
|
|
|
|
ConfigVar::~ConfigVar()
|
|
{
|
|
pd.reset();
|
|
}
|
|
|
|
ConfigVar & ConfigVar::operator = (const ConfigVar &src)
|
|
{
|
|
if(src.pd == pd)
|
|
return *this;
|
|
else
|
|
pd = src.pd;
|
|
|
|
return *this;
|
|
}
|
|
|
|
void ConfigVar::resetOffset()
|
|
{
|
|
pd->offset = 0;
|
|
}
|
|
|
|
int ConfigVar::read(byte *buffer_, int bytes) const
|
|
{
|
|
int toCopy = MIN( bytes, pd->buffer.size() - pd->offset );
|
|
|
|
if(toCopy > 0)
|
|
memcpy( buffer_, pd->buffer.data() + pd->offset, toCopy );
|
|
|
|
pd->offset += toCopy;
|
|
|
|
return toCopy;
|
|
}
|
|
|
|
int ConfigVar::write(const byte *data, int bytes)
|
|
{
|
|
if(pd->buffer.size() == (unsigned int)pd->offset)
|
|
{
|
|
pd->buffer.append( (const char *)data, bytes );
|
|
} else
|
|
{
|
|
pd->buffer.insert( pd->offset, (const char *)data, bytes );
|
|
}
|
|
|
|
pd->offset += bytes;
|
|
|
|
return bytes;
|
|
}
|
|
|
|
int ConfigVar::size() const
|
|
{
|
|
return pd->buffer.size();
|
|
}
|
|
|
|
const char *ConfigVar::buffer() const
|
|
{
|
|
return pd->buffer.data();
|
|
}
|
|
|
|
int ConfigVar::at() const
|
|
{
|
|
return pd->offset;
|
|
}
|
|
|
|
void ConfigVar::writeString(const char *data, int bytes)
|
|
{
|
|
writeInt( bytes );
|
|
write( (const byte *)data, bytes );
|
|
}
|
|
|
|
|
|
// convert integer to BER encoded integer
|
|
void ConfigVar::writeInt(int val)
|
|
{
|
|
// we can represent 7 bits per char output, so a 32bit number may take up
|
|
// to 5 bytes.
|
|
// first byte: 0x0000007f 0111,1111
|
|
// second byte: 0x00003f80 0011,1111 1000,0000
|
|
// third byte: 0x001fb000 0000,0000 0001,1111 1100,0000 0000,0000
|
|
// fourth byte: 0x0fe00000 0000,1111 1110,0000
|
|
// fifth byte: 0xf0000000 1111,0000
|
|
byte digit[5];
|
|
|
|
digit[4] = (byte)((val & 0x0000007f));
|
|
digit[3] = 0x80 | (byte)((val & 0x00003f80) >> 7);
|
|
digit[2] = 0x80 | (byte)((val & 0x001fc000) >> 14);
|
|
digit[1] = 0x80 | (byte)((val & 0x0fe00000) >> 21);
|
|
digit[0] = 0x80 | (byte)((val & 0xf0000000) >> 28);
|
|
|
|
// find the starting point - we only need to output starting at the most
|
|
// significant non-zero digit..
|
|
int start = 0;
|
|
while(digit[start] == 0x80)
|
|
++start;
|
|
|
|
write( digit + start, 5-start );
|
|
}
|
|
|
|
int ConfigVar::readInt() const
|
|
{
|
|
const byte * buf = (const byte *)buffer();
|
|
int bytes = this->size();
|
|
int offset = at();
|
|
int value = 0;
|
|
bool highBitSet;
|
|
|
|
rAssert( offset < bytes );
|
|
|
|
do
|
|
{
|
|
byte tmp = buf[offset++];
|
|
highBitSet = tmp & 0x80;
|
|
|
|
value = (value << 7) | (int)(tmp & 0x7f);
|
|
} while(highBitSet && offset < bytes);
|
|
|
|
pd->offset = offset;
|
|
|
|
// should never end up with a negative number..
|
|
rAssert( value >= 0 );
|
|
|
|
return value;
|
|
}
|
|
|
|
int ConfigVar::readInt( int defaultValue ) const
|
|
{
|
|
int bytes = this->size();
|
|
int offset = at();
|
|
|
|
if(offset >= bytes)
|
|
return defaultValue;
|
|
else
|
|
return readInt();
|
|
}
|
|
|
|
bool ConfigVar::readBool( bool defaultValue ) const
|
|
{
|
|
int tmp = readInt( defaultValue ? 1 : 0 );
|
|
return (tmp != 0);
|
|
}
|
|
|
|
ConfigVar & operator << (ConfigVar &src, bool value)
|
|
{
|
|
src.writeInt( value ? 1 : 0 );
|
|
return src;
|
|
}
|
|
|
|
ConfigVar & operator << (ConfigVar &src, int var)
|
|
{
|
|
src.writeInt( var );
|
|
return src;
|
|
}
|
|
|
|
ConfigVar & operator << (ConfigVar &src, const std::string &str)
|
|
{
|
|
src.writeString( str.data(), str.length() );
|
|
return src;
|
|
}
|
|
|
|
const ConfigVar & operator >> (const ConfigVar &src, bool &result)
|
|
{
|
|
int tmp = src.readInt();
|
|
result = (tmp != 0);
|
|
return src;
|
|
}
|
|
|
|
const ConfigVar & operator >> (const ConfigVar &src, int &result)
|
|
{
|
|
result = src.readInt();
|
|
return src;
|
|
}
|
|
|
|
const ConfigVar & operator >> (const ConfigVar &src, std::string &result)
|
|
{
|
|
int length = src.readInt();
|
|
LOG_IF(WARNING, length <= 0) << "Invalid config length " << length;
|
|
|
|
int readLen;
|
|
|
|
byte tmpBuf[32];
|
|
if(length > (int)sizeof(tmpBuf))
|
|
{
|
|
byte *ptr = new byte[length];
|
|
readLen = src.read( ptr, length );
|
|
result.assign( (char*)ptr, length );
|
|
delete[] ptr;
|
|
} else
|
|
{
|
|
readLen = src.read( tmpBuf, length );
|
|
result.assign( (char*)tmpBuf, length );
|
|
}
|
|
|
|
if(readLen != length)
|
|
{
|
|
VLOG(1) << "string encoded as size " << length
|
|
<< " bytes, read " << readLen;
|
|
}
|
|
|
|
rAssert(readLen == length);
|
|
|
|
return src;
|
|
}
|
|
|
|
} // namespace encfs
|