@ -23,19 +23,6 @@ namespace ROCKSDB_NAMESPACE {
# ifndef ROCKSDB_LITE
class EncryptedSequentialFile : public SequentialFile {
private :
std : : unique_ptr < SequentialFile > file_ ;
std : : unique_ptr < BlockAccessCipherStream > stream_ ;
uint64_t offset_ ;
size_t prefixLength_ ;
public :
// Default ctor. Given underlying sequential file is supposed to be at
// offset == prefixLength.
EncryptedSequentialFile ( SequentialFile * f , BlockAccessCipherStream * s , size_t prefixLength )
: file_ ( f ) , stream_ ( s ) , offset_ ( prefixLength ) , prefixLength_ ( prefixLength ) {
}
// Read up to "n" bytes from the file. "scratch[0..n-1]" may be
// written by this routine. Sets "*result" to the data that was
@ -45,83 +32,73 @@ class EncryptedSequentialFile : public SequentialFile {
// If an error was encountered, returns a non-OK status.
//
// REQUIRES: External synchronization
Status Read ( size_t n , Slice * result , char * scratch ) override {
assert ( scratch ) ;
Status status = file_ - > Read ( n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset_ , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
offset_ + = result - > size ( ) ; // We've already ready data from disk, so update
// offset_ even if decryption fails.
Status EncryptedSequentialFile : : Read ( size_t n , Slice * result , char * scratch ) {
assert ( scratch ) ;
Status status = file_ - > Read ( n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset_ , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
offset_ + = result - > size ( ) ; // We've already ready data from disk, so update
// offset_ even if decryption fails.
return status ;
}
// Skip "n" bytes from the file. This is guaranteed to be no
// slower that reading the same data, but may be faster.
//
// If end of file is reached, skipping will stop at the end of the
// file, and Skip will return OK.
//
// REQUIRES: External synchronization
Status Skip ( uint64_t n ) override {
auto status = file_ - > Skip ( n ) ;
if ( ! status . ok ( ) ) {
return status ;
}
offset_ + = n ;
// Skip "n" bytes from the file. This is guaranteed to be no
// slower that reading the same data, but may be faster.
//
// If end of file is reached, skipping will stop at the end of the
// file, and Skip will return OK.
//
// REQUIRES: External synchronization
Status EncryptedSequentialFile : : Skip ( uint64_t n ) {
auto status = file_ - > Skip ( n ) ;
if ( ! status . ok ( ) ) {
return status ;
}
offset_ + = n ;
return status ;
}
// Indicates the upper layers if the current SequentialFile implementation
// uses direct IO.
bool use_direct_io ( ) const override { return file_ - > use_direct_io ( ) ; }
// Indicates the upper layers if the current SequentialFile implementation
// uses direct IO.
bool EncryptedSequentialFile : : use_direct_io ( ) const {
return file_ - > use_direct_io ( ) ;
}
// Use the returned alignment value to allocate
// aligned buffer for Direct I/O
size_t GetRequiredBufferAlignment ( ) const override {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
// Use the returned alignment value to allocate
// aligned buffer for Direct I/O
size_t EncryptedSequentialFile : : GetRequiredBufferAlignment ( ) const {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
// Remove any kind of caching of data from the offset to offset+length
// of this file. If the length is 0, then it refers to the end of file.
// If the system is not caching the file contents, then this is a noop.
Status InvalidateCache ( size_t offset , size_t length ) override {
return file_ - > InvalidateCache ( offset + prefixLength_ , length ) ;
}
Status EncryptedSequentialFile : : InvalidateCache ( size_t offset , size_t length ) {
return file_ - > InvalidateCache ( offset + prefixLength_ , length ) ;
}
// Positioned Read for direct I/O
// If Direct I/O enabled, offset, n, and scratch should be properly aligned
Status PositionedRead ( uint64_t offset , size_t n , Slice * result ,
char * scratch ) override {
assert ( scratch ) ;
offset + = prefixLength_ ; // Skip prefix
auto status = file_ - > PositionedRead ( offset , n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
offset_ = offset + result - > size ( ) ;
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
Status EncryptedSequentialFile : : PositionedRead ( uint64_t offset , size_t n ,
Slice * result , char * scratch ) {
assert ( scratch ) ;
offset + = prefixLength_ ; // Skip prefix
auto status = file_ - > PositionedRead ( offset , n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
} ;
// A file abstraction for randomly reading the contents of a file.
class EncryptedRandomAccessFile : public RandomAccessFile {
private :
std : : unique_ptr < RandomAccessFile > file_ ;
std : : unique_ptr < BlockAccessCipherStream > stream_ ;
size_t prefixLength_ ;
public :
EncryptedRandomAccessFile ( RandomAccessFile * f , BlockAccessCipherStream * s , size_t prefixLength )
: file_ ( f ) , stream_ ( s ) , prefixLength_ ( prefixLength ) { }
offset_ = offset + result - > size ( ) ;
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
return status ;
}
// Read up to "n" bytes from the file starting at "offset".
// "scratch[0..n-1]" may be written by this routine. Sets "*result"
@ -133,26 +110,26 @@ class EncryptedRandomAccessFile : public RandomAccessFile {
//
// Safe for concurrent use by multiple threads.
// If Direct I/O enabled, offset, n, and scratch should be aligned properly.
Status Read ( uint64_t offset , size_t n , Slice * result ,
char * scratch ) const override {
assert ( scratch ) ;
offset + = prefixLength_ ;
auto status = file_ - > Read ( offset , n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
Status EncryptedRandomAccessFile : : Read ( uint64_t offset , size_t n , Slice * result ,
char * scratch ) const {
assert ( scratch ) ;
offset + = prefixLength_ ;
auto status = file_ - > Read ( offset , n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
return status ;
}
// Readahead the file starting from offset by n bytes for caching.
Status Prefetch ( uint64_t offset , size_t n ) override {
//return Status::OK();
return file_ - > Prefetch ( offset + prefixLength_ , n ) ;
}
Status EncryptedRandomAccessFile : : Prefetch ( uint64_t offset , size_t n ) {
// return Status::OK();
return file_ - > Prefetch ( offset + prefixLength_ , n ) ;
}
// Tries to get an unique ID for this file that will be the same each time
// the file is opened (and will stay the same while the file is open).
@ -169,132 +146,128 @@ class EncryptedRandomAccessFile : public RandomAccessFile {
// a single varint.
//
// Note: these IDs are only valid for the duration of the process.
size_t GetUniqueId ( char * id , size_t max_size ) const override {
return file_ - > GetUniqueId ( id , max_size ) ;
} ;
size_t EncryptedRandomAccessFile : : GetUniqueId ( char * id , size_t max_size ) const {
return file_ - > GetUniqueId ( id , max_size ) ;
} ;
void Hint ( AccessPattern pattern ) override { file_ - > Hint ( pattern ) ; }
void EncryptedRandomAccessFile : : Hint ( AccessPattern pattern ) {
file_ - > Hint ( pattern ) ;
}
// Indicates the upper layers if the current RandomAccessFile implementation
// uses direct IO.
bool use_direct_io ( ) const override { return file_ - > use_direct_io ( ) ; }
bool EncryptedRandomAccessFile : : use_direct_io ( ) const {
return file_ - > use_direct_io ( ) ;
}
// Use the returned alignment value to allocate
// aligned buffer for Direct I/O
size_t GetRequiredBufferAlignment ( ) const override {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
size_t EncryptedRandomAccessFile : : GetRequiredBufferAlignment ( ) const {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
// Remove any kind of caching of data from the offset to offset+length
// of this file. If the length is 0, then it refers to the end of file.
// If the system is not caching the file contents, then this is a noop.
Status InvalidateCache ( size_t offset , size_t length ) override {
return file_ - > InvalidateCache ( offset + prefixLength_ , length ) ;
}
} ;
Status EncryptedRandomAccessFile : : InvalidateCache ( size_t offset ,
size_t length ) {
return file_ - > InvalidateCache ( offset + prefixLength_ , length ) ;
}
// A file abstraction for sequential writing. The implementation
// must provide buffering since callers may append small fragments
// at a time to the file.
class EncryptedWritableFile : public WritableFileWrapper {
private :
std : : unique_ptr < WritableFile > file_ ;
std : : unique_ptr < BlockAccessCipherStream > stream_ ;
size_t prefixLength_ ;
public :
// Default ctor. Prefix is assumed to be written already.
EncryptedWritableFile ( WritableFile * f , BlockAccessCipherStream * s , size_t prefixLength )
: WritableFileWrapper ( f ) , file_ ( f ) , stream_ ( s ) , prefixLength_ ( prefixLength ) { }
Status Append ( const Slice & data ) override {
AlignedBuffer buf ;
Status status ;
Slice dataToAppend ( data ) ;
if ( data . size ( ) > 0 ) {
auto offset = file_ - > GetFileSize ( ) ; // size including prefix
// Encrypt in cloned buffer
buf . Alignment ( GetRequiredBufferAlignment ( ) ) ;
buf . AllocateNewBuffer ( data . size ( ) ) ;
// TODO (sagar0): Modify AlignedBuffer.Append to allow doing a memmove
// so that the next two lines can be replaced with buf.Append().
memmove ( buf . BufferStart ( ) , data . data ( ) , data . size ( ) ) ;
buf . Size ( data . size ( ) ) ;
{
PERF_TIMER_GUARD ( encrypt_data_nanos ) ;
status = stream_ - > Encrypt ( offset , buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
if ( ! status . ok ( ) ) {
return status ;
}
dataToAppend = Slice ( buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
Status EncryptedWritableFile : : Append ( const Slice & data ) {
AlignedBuffer buf ;
Status status ;
Slice dataToAppend ( data ) ;
if ( data . size ( ) > 0 ) {
auto offset = file_ - > GetFileSize ( ) ; // size including prefix
// Encrypt in cloned buffer
buf . Alignment ( GetRequiredBufferAlignment ( ) ) ;
buf . AllocateNewBuffer ( data . size ( ) ) ;
// TODO (sagar0): Modify AlignedBuffer.Append to allow doing a memmove
// so that the next two lines can be replaced with buf.Append().
memmove ( buf . BufferStart ( ) , data . data ( ) , data . size ( ) ) ;
buf . Size ( data . size ( ) ) ;
{
PERF_TIMER_GUARD ( encrypt_data_nanos ) ;
status = stream_ - > Encrypt ( offset , buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
status = file_ - > Append ( dataToAppend ) ;
if ( ! status . ok ( ) ) {
return status ;
}
dataToAppend = Slice ( buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
status = file_ - > Append ( dataToAppend ) ;
if ( ! status . ok ( ) ) {
return status ;
}
return status ;
}
Status PositionedAppend ( const Slice & data , uint64_t offset ) override {
AlignedBuffer buf ;
Status status ;
Slice dataToAppend ( data ) ;
offset + = prefixLength_ ;
if ( data . size ( ) > 0 ) {
// Encrypt in cloned buffer
buf . Alignment ( GetRequiredBufferAlignment ( ) ) ;
buf . AllocateNewBuffer ( data . size ( ) ) ;
memmove ( buf . BufferStart ( ) , data . data ( ) , data . size ( ) ) ;
buf . Size ( data . size ( ) ) ;
{
PERF_TIMER_GUARD ( encrypt_data_nanos ) ;
status = stream_ - > Encrypt ( offset , buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
if ( ! status . ok ( ) ) {
return status ;
}
dataToAppend = Slice ( buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
Status EncryptedWritableFile : : PositionedAppend ( const Slice & data ,
uint64_t offset ) {
AlignedBuffer buf ;
Status status ;
Slice dataToAppend ( data ) ;
offset + = prefixLength_ ;
if ( data . size ( ) > 0 ) {
// Encrypt in cloned buffer
buf . Alignment ( GetRequiredBufferAlignment ( ) ) ;
buf . AllocateNewBuffer ( data . size ( ) ) ;
memmove ( buf . BufferStart ( ) , data . data ( ) , data . size ( ) ) ;
buf . Size ( data . size ( ) ) ;
{
PERF_TIMER_GUARD ( encrypt_data_nanos ) ;
status = stream_ - > Encrypt ( offset , buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
status = file_ - > PositionedAppend ( dataToAppend , offset ) ;
if ( ! status . ok ( ) ) {
return status ;
}
dataToAppend = Slice ( buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
status = file_ - > PositionedAppend ( dataToAppend , offset ) ;
if ( ! status . ok ( ) ) {
return status ;
}
return status ;
}
// Indicates the upper layers if the current WritableFile implementation
// uses direct IO.
bool use_direct_io ( ) const override { return file_ - > use_direct_io ( ) ; }
bool EncryptedWritableFile : : use_direct_io ( ) const {
return file_ - > use_direct_io ( ) ;
}
// Use the returned alignment value to allocate
// aligned buffer for Direct I/O
size_t GetRequiredBufferAlignment ( ) const override {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
size_t EncryptedWritableFile : : GetRequiredBufferAlignment ( ) const {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
/*
* Get the size of valid data in the file .
*/
uint64_t GetFileSize ( ) override {
return file_ - > GetFileSize ( ) - prefixLength_ ;
}
/*
* Get the size of valid data in the file .
*/
uint64_t EncryptedWritableFile : : GetFileSize ( ) {
return file_ - > GetFileSize ( ) - prefixLength_ ;
}
// Truncate is necessary to trim the file to the correct size
// before closing. It is not always possible to keep track of the file
// size due to whole pages writes. The behavior is undefined if called
// with other writes to follow.
Status Truncate ( uint64_t size ) override {
return file_ - > Truncate ( size + prefixLength_ ) ;
}
Status EncryptedWritableFile : : Truncate ( uint64_t size ) {
return file_ - > Truncate ( size + prefixLength_ ) ;
}
// Remove any kind of caching of data from the offset to offset+length
// of this file. If the length is 0, then it refers to the end of file.
// If the system is not caching the file contents, then this is a noop.
// This call has no effect on dirty pages in the cache.
Status InvalidateCache ( size_t offset , size_t length ) override {
return file_ - > InvalidateCache ( offset + prefixLength_ , length ) ;
}
Status EncryptedWritableFile : : InvalidateCache ( size_t offset , size_t length ) {
return file_ - > InvalidateCache ( offset + prefixLength_ , length ) ;
}
// Sync a file range with disk.
// offset is the starting byte of the file range to be synchronized.
@ -302,111 +275,103 @@ class EncryptedWritableFile : public WritableFileWrapper {
// This asks the OS to initiate flushing the cached data to disk,
// without waiting for completion.
// Default implementation does nothing.
Status RangeSync ( uint64_t offset , uint64_t nbytes ) override {
return file_ - > RangeSync ( offset + prefixLength_ , nbytes ) ;
}
Status EncryptedWritableFile : : RangeSync ( uint64_t offset , uint64_t nbytes ) {
return file_ - > RangeSync ( offset + prefixLength_ , nbytes ) ;
}
// PrepareWrite performs any necessary preparation for a write
// before the write actually occurs. This allows for pre-allocation
// of space on devices where it can result in less file
// fragmentation and/or less waste from over-zealous filesystem
// pre-allocation.
void PrepareWrite ( size_t offset , size_t len ) override {
file_ - > PrepareWrite ( offset + prefixLength_ , len ) ;
}
void EncryptedWritableFile : : PrepareWrite ( size_t offset , size_t len ) {
file_ - > PrepareWrite ( offset + prefixLength_ , len ) ;
}
// Pre-allocates space for a file.
Status Allocate ( uint64_t offset , uint64_t len ) override {
return file_ - > Allocate ( offset + prefixLength_ , len ) ;
}
} ;
Status EncryptedWritableFile : : Allocate ( uint64_t offset , uint64_t len ) {
return file_ - > Allocate ( offset + prefixLength_ , len ) ;
}
// A file abstraction for random reading and writing.
class EncryptedRandomRWFile : public RandomRWFile {
private :
std : : unique_ptr < RandomRWFile > file_ ;
std : : unique_ptr < BlockAccessCipherStream > stream_ ;
size_t prefixLength_ ;
public :
EncryptedRandomRWFile ( RandomRWFile * f , BlockAccessCipherStream * s , size_t prefixLength )
: file_ ( f ) , stream_ ( s ) , prefixLength_ ( prefixLength ) { }
// Indicates if the class makes use of direct I/O
// If false you must pass aligned buffer to Write()
bool use_direct_io ( ) const override { return file_ - > use_direct_io ( ) ; }
// Indicates if the class makes use of direct I/O
// If false you must pass aligned buffer to Write()
bool EncryptedRandomRWFile : : use_direct_io ( ) const {
return file_ - > use_direct_io ( ) ;
}
// Use the returned alignment value to allocate
// aligned buffer for Direct I/O
size_t GetRequiredBufferAlignment ( ) const override {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
size_t EncryptedRandomRWFile : : GetRequiredBufferAlignment ( ) const {
return file_ - > GetRequiredBufferAlignment ( ) ;
}
// Write bytes in `data` at offset `offset`, Returns Status::OK() on success.
// Pass aligned buffer when use_direct_io() returns true.
Status Write ( uint64_t offset , const Slice & data ) override {
AlignedBuffer buf ;
Status status ;
Slice dataToWrite ( data ) ;
offset + = prefixLength_ ;
if ( data . size ( ) > 0 ) {
// Encrypt in cloned buffer
buf . Alignment ( GetRequiredBufferAlignment ( ) ) ;
buf . AllocateNewBuffer ( data . size ( ) ) ;
memmove ( buf . BufferStart ( ) , data . data ( ) , data . size ( ) ) ;
buf . Size ( data . size ( ) ) ;
{
PERF_TIMER_GUARD ( encrypt_data_nanos ) ;
status = stream_ - > Encrypt ( offset , buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
if ( ! status . ok ( ) ) {
return status ;
}
dataToWrite = Slice ( buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
Status EncryptedRandomRWFile : : Write ( uint64_t offset , const Slice & data ) {
AlignedBuffer buf ;
Status status ;
Slice dataToWrite ( data ) ;
offset + = prefixLength_ ;
if ( data . size ( ) > 0 ) {
// Encrypt in cloned buffer
buf . Alignment ( GetRequiredBufferAlignment ( ) ) ;
buf . AllocateNewBuffer ( data . size ( ) ) ;
memmove ( buf . BufferStart ( ) , data . data ( ) , data . size ( ) ) ;
buf . Size ( data . size ( ) ) ;
{
PERF_TIMER_GUARD ( encrypt_data_nanos ) ;
status = stream_ - > Encrypt ( offset , buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
status = file_ - > Write ( offset , dataToWrite ) ;
return status ;
if ( ! status . ok ( ) ) {
return status ;
}
dataToWrite = Slice ( buf . BufferStart ( ) , buf . CurrentSize ( ) ) ;
}
status = file_ - > Write ( offset , dataToWrite ) ;
return status ;
}
// Read up to `n` bytes starting from offset `offset` and store them in
// result, provided `scratch` size should be at least `n`.
// Returns Status::OK() on success.
Status Read ( uint64_t offset , size_t n , Slice * result ,
char * scratch ) const override {
assert ( scratch ) ;
offset + = prefixLength_ ;
auto status = file_ - > Read ( offset , n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
Status EncryptedRandomRWFile : : Read ( uint64_t offset , size_t n , Slice * result ,
char * scratch ) const {
assert ( scratch ) ;
offset + = prefixLength_ ;
auto status = file_ - > Read ( offset , n , result , scratch ) ;
if ( ! status . ok ( ) ) {
return status ;
}
{
PERF_TIMER_GUARD ( decrypt_data_nanos ) ;
status = stream_ - > Decrypt ( offset , ( char * ) result - > data ( ) , result - > size ( ) ) ;
}
return status ;
}
Status Flush ( ) override { return file_ - > Flush ( ) ; }
Status EncryptedRandomRWFile : : Flush ( ) { return file_ - > Flush ( ) ; }
Status Sync ( ) override { return file_ - > Sync ( ) ; }
Status EncryptedRandomRWFile : : Sync ( ) { return file_ - > Sync ( ) ; }
Status Fsync ( ) override { return file_ - > Fsync ( ) ; }
Status EncryptedRandomRWFile : : Fsync ( ) { return file_ - > Fsync ( ) ; }
Status Close ( ) override { return file_ - > Close ( ) ; }
} ;
Status EncryptedRandomRWFile : : Close ( ) { return file_ - > Close ( ) ; }
// EncryptedEnv implements an Env wrapper that adds encryption to files stored on disk.
// EncryptedEnv implements an Env wrapper that adds encryption to files stored
// on disk.
class EncryptedEnv : public EnvWrapper {
public :
EncryptedEnv ( Env * base_env , EncryptionProvider * provider )
EncryptedEnv ( Env * base_env , EncryptionProvider * provider )
: EnvWrapper ( base_env ) {
provider_ = provider ;
}
// NewSequentialFile opens a file for sequential reading.
Status NewSequentialFile ( const std : : string & fname ,
std : : unique_ptr < SequentialFile > * result ,
const EnvOptions & options ) override {
virtual Status NewSequentialFile ( const std : : string & fname ,
std : : unique_ptr < SequentialFile > * result ,
const EnvOptions & options ) override {
result - > reset ( ) ;
if ( options . use_mmap_reads ) {
return Status : : InvalidArgument ( ) ;
@ -425,7 +390,8 @@ class EncryptedEnv : public EnvWrapper {
// Read prefix
prefixBuf . Alignment ( underlying - > GetRequiredBufferAlignment ( ) ) ;
prefixBuf . AllocateNewBuffer ( prefixLength ) ;
status = underlying - > Read ( prefixLength , & prefixSlice , prefixBuf . BufferStart ( ) ) ;
status =
underlying - > Read ( prefixLength , & prefixSlice , prefixBuf . BufferStart ( ) ) ;
if ( ! status . ok ( ) ) {
return status ;
}
@ -433,18 +399,20 @@ class EncryptedEnv : public EnvWrapper {
}
// Create cipher stream
std : : unique_ptr < BlockAccessCipherStream > stream ;
status = provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
status =
provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
if ( ! status . ok ( ) ) {
return status ;
}
( * result ) = std : : unique_ptr < SequentialFile > ( new EncryptedSequentialFile ( underlying . release ( ) , stream . release ( ) , prefixLength ) ) ;
( * result ) = std : : unique_ptr < SequentialFile > ( new EncryptedSequentialFile (
std : : move ( underlying ) , std : : move ( stream ) , prefixLength ) ) ;
return Status : : OK ( ) ;
}
// NewRandomAccessFile opens a file for random read access.
Status NewRandomAccessFile ( const std : : string & fname ,
std : : unique_ptr < RandomAccessFile > * result ,
const EnvOptions & options ) override {
virtual Status NewRandomAccessFile ( const std : : string & fname ,
std : : unique_ptr < RandomAccessFile > * result ,
const EnvOptions & options ) override {
result - > reset ( ) ;
if ( options . use_mmap_reads ) {
return Status : : InvalidArgument ( ) ;
@ -463,7 +431,8 @@ class EncryptedEnv : public EnvWrapper {
// Read prefix
prefixBuf . Alignment ( underlying - > GetRequiredBufferAlignment ( ) ) ;
prefixBuf . AllocateNewBuffer ( prefixLength ) ;
status = underlying - > Read ( 0 , prefixLength , & prefixSlice , prefixBuf . BufferStart ( ) ) ;
status = underlying - > Read ( 0 , prefixLength , & prefixSlice ,
prefixBuf . BufferStart ( ) ) ;
if ( ! status . ok ( ) ) {
return status ;
}
@ -471,18 +440,20 @@ class EncryptedEnv : public EnvWrapper {
}
// Create cipher stream
std : : unique_ptr < BlockAccessCipherStream > stream ;
status = provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
status =
provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
if ( ! status . ok ( ) ) {
return status ;
}
( * result ) = std : : unique_ptr < RandomAccessFile > ( new EncryptedRandomAccessFile ( underlying . release ( ) , stream . release ( ) , prefixLength ) ) ;
( * result ) = std : : unique_ptr < RandomAccessFile > ( new EncryptedRandomAccessFile (
std : : move ( underlying ) , std : : move ( stream ) , prefixLength ) ) ;
return Status : : OK ( ) ;
}
// NewWritableFile opens a file for sequential writing.
Status NewWritableFile ( const std : : string & fname ,
std : : unique_ptr < WritableFile > * result ,
const EnvOptions & options ) override {
virtual Status NewWritableFile ( const std : : string & fname ,
std : : unique_ptr < WritableFile > * result ,
const EnvOptions & options ) override {
result - > reset ( ) ;
if ( options . use_mmap_writes ) {
return Status : : InvalidArgument ( ) ;
@ -512,11 +483,13 @@ class EncryptedEnv : public EnvWrapper {
}
// Create cipher stream
std : : unique_ptr < BlockAccessCipherStream > stream ;
status = provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
status =
provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
if ( ! status . ok ( ) ) {
return status ;
}
( * result ) = std : : unique_ptr < WritableFile > ( new EncryptedWritableFile ( underlying . release ( ) , stream . release ( ) , prefixLength ) ) ;
( * result ) = std : : unique_ptr < WritableFile > ( new EncryptedWritableFile (
std : : move ( underlying ) , std : : move ( stream ) , prefixLength ) ) ;
return Status : : OK ( ) ;
}
@ -527,9 +500,9 @@ class EncryptedEnv : public EnvWrapper {
// returns non-OK.
//
// The returned file will only be accessed by one thread at a time.
Status ReopenWritableFile ( const std : : string & fname ,
std : : unique_ptr < WritableFile > * result ,
const EnvOptions & options ) override {
virtual Status ReopenWritableFile ( const std : : string & fname ,
std : : unique_ptr < WritableFile > * result ,
const EnvOptions & options ) override {
result - > reset ( ) ;
if ( options . use_mmap_writes ) {
return Status : : InvalidArgument ( ) ;
@ -559,26 +532,29 @@ class EncryptedEnv : public EnvWrapper {
}
// Create cipher stream
std : : unique_ptr < BlockAccessCipherStream > stream ;
status = provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
status =
provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
if ( ! status . ok ( ) ) {
return status ;
}
( * result ) = std : : unique_ptr < WritableFile > ( new EncryptedWritableFile ( underlying . release ( ) , stream . release ( ) , prefixLength ) ) ;
( * result ) = std : : unique_ptr < WritableFile > ( new EncryptedWritableFile (
std : : move ( underlying ) , std : : move ( stream ) , prefixLength ) ) ;
return Status : : OK ( ) ;
}
// Reuse an existing file by renaming it and opening it as writable.
Status ReuseWritableFile ( const std : : string & fname ,
const std : : string & old_fname ,
std : : unique_ptr < WritableFile > * result ,
const EnvOptions & options ) override {
virtual Status ReuseWritableFile ( const std : : string & fname ,
const std : : string & old_fname ,
std : : unique_ptr < WritableFile > * result ,
const EnvOptions & options ) override {
result - > reset ( ) ;
if ( options . use_mmap_writes ) {
return Status : : InvalidArgument ( ) ;
}
// Open file using underlying Env implementation
std : : unique_ptr < WritableFile > underlying ;
Status status = EnvWrapper : : ReuseWritableFile ( fname , old_fname , & underlying , options ) ;
Status status =
EnvWrapper : : ReuseWritableFile ( fname , old_fname , & underlying , options ) ;
if ( ! status . ok ( ) ) {
return status ;
}
@ -601,11 +577,13 @@ class EncryptedEnv : public EnvWrapper {
}
// Create cipher stream
std : : unique_ptr < BlockAccessCipherStream > stream ;
status = provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
status =
provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
if ( ! status . ok ( ) ) {
return status ;
}
( * result ) = std : : unique_ptr < WritableFile > ( new EncryptedWritableFile ( underlying . release ( ) , stream . release ( ) , prefixLength ) ) ;
( * result ) = std : : unique_ptr < WritableFile > ( new EncryptedWritableFile (
std : : move ( underlying ) , std : : move ( stream ) , prefixLength ) ) ;
return Status : : OK ( ) ;
}
@ -614,9 +592,9 @@ class EncryptedEnv : public EnvWrapper {
// *result and returns OK. On failure returns non-OK.
//
// The returned file will only be accessed by one thread at a time.
Status NewRandomRWFile ( const std : : string & fname ,
std : : unique_ptr < RandomRWFile > * result ,
const EnvOptions & options ) override {
virtual Status NewRandomRWFile ( const std : : string & fname ,
std : : unique_ptr < RandomRWFile > * result ,
const EnvOptions & options ) override {
result - > reset ( ) ;
if ( options . use_mmap_reads | | options . use_mmap_writes ) {
return Status : : InvalidArgument ( ) ;
@ -639,14 +617,16 @@ class EncryptedEnv : public EnvWrapper {
prefixBuf . AllocateNewBuffer ( prefixLength ) ;
if ( ! isNewFile ) {
// File already exists, read prefix
status = underlying - > Read ( 0 , prefixLength , & prefixSlice , prefixBuf . BufferStart ( ) ) ;
status = underlying - > Read ( 0 , prefixLength , & prefixSlice ,
prefixBuf . BufferStart ( ) ) ;
if ( ! status . ok ( ) ) {
return status ;
}
prefixBuf . Size ( prefixLength ) ;
} else {
// File is new, initialize & write prefix
provider_ - > CreateNewPrefix ( fname , prefixBuf . BufferStart ( ) , prefixLength ) ;
provider_ - > CreateNewPrefix ( fname , prefixBuf . BufferStart ( ) ,
prefixLength ) ;
prefixBuf . Size ( prefixLength ) ;
prefixSlice = Slice ( prefixBuf . BufferStart ( ) , prefixBuf . CurrentSize ( ) ) ;
// Write prefix
@ -658,40 +638,51 @@ class EncryptedEnv : public EnvWrapper {
}
// Create cipher stream
std : : unique_ptr < BlockAccessCipherStream > stream ;
status = provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
status =
provider_ - > CreateCipherStream ( fname , options , prefixSlice , & stream ) ;
if ( ! status . ok ( ) ) {
return status ;
}
( * result ) = std : : unique_ptr < RandomRWFile > ( new EncryptedRandomRWFile ( underlying . release ( ) , stream . release ( ) , prefixLength ) ) ;
( * result ) = std : : unique_ptr < RandomRWFile > ( new EncryptedRandomRWFile (
std : : move ( underlying ) , std : : move ( stream ) , prefixLength ) ) ;
return Status : : OK ( ) ;
}
// Store in *result the attributes of the children of the specified directory.
// In case the implementation lists the directory prior to iterating the files
// and files are concurrently deleted, the deleted files will be omitted from
// Store in *result the attributes of the children of the specified
// directory.
// In case the implementation lists the directory prior to iterating the
// files
// and files are concurrently deleted, the deleted files will be omitted
// from
// result.
// The name attributes are relative to "dir".
// Original contents of *results are dropped.
// Returns OK if "dir" exists and "*result" contains its children.
// NotFound if "dir" does not exist, the calling process does not have
// NotFound if "dir" does not exist, the calling process does not
// have
// permission to access "dir", or if "dir" is invalid.
// IOError if an IO Error was encountered
Status GetChildrenFileAttributes (
virtual Status GetChildrenFileAttributes (
const std : : string & dir , std : : vector < FileAttributes > * result ) override {
auto status = EnvWrapper : : GetChildrenFileAttributes ( dir , result ) ;
if ( ! status . ok ( ) ) {
return status ;
}
size_t prefixLength = provider_ - > GetPrefixLength ( ) ;
for ( auto it = std : : begin ( * result ) ; it ! = std : : end ( * result ) ; + + it ) {
assert ( it - > size_bytes > = prefixLength ) ;
for ( auto it = std : : begin ( * result ) ; it ! = std : : end ( * result ) ; + + it ) {
// assert(it->size_bytes >= prefixLength);
// breaks env_basic_test when called on directory containing
// directories
// which makes subtraction of prefixLength worrisome since
// FileAttributes does not identify directories
it - > size_bytes - = prefixLength ;
}
return Status : : OK ( ) ;
}
// Store the size of fname in *file_size.
Status GetFileSize ( const std : : string & fname , uint64_t * file_size ) override {
virtual Status GetFileSize ( const std : : string & fname ,
uint64_t * file_size ) override {
auto status = EnvWrapper : : GetFileSize ( fname , file_size ) ;
if ( ! status . ok ( ) ) {
return status ;
@ -703,7 +694,7 @@ class EncryptedEnv : public EnvWrapper {
}
private :
EncryptionProvider * provider_ ;
EncryptionProvider * provider_ ;
} ;
// Returns an Env that encrypts data when stored on disk and decrypts data when