File: bundle.hh

package info (click to toggle)
zbackup 1.5-4
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 868 kB
  • sloc: cpp: 6,957; ansic: 468; python: 207; makefile: 10
file content (123 lines) | stat: -rw-r--r-- 3,806 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) 2012-2014 Konstantin Isakov <ikm@zbackup.org> and ZBackup contributors, see CONTRIBUTORS
// Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE

#ifndef BUNDLE_HH_INCLUDED
#define BUNDLE_HH_INCLUDED

#include <stddef.h>
#include <string.h>
#include <exception>
#include <map>
#include <string>
#include <utility>

#include "encryption_key.hh"
#include "ex.hh"
#include "nocopy.hh"
#include "static_assert.hh"
#include "zbackup.pb.h"
#include "encrypted_file.hh"
#include "config.hh"

namespace Bundle {

using std::string;
using std::pair;
using std::map;

enum
{
  /// The number of bytes the bundle id has. We chose 192-bit just to be on
  /// the safer side. It is also a multiple of 8 bytes, which is good for
  /// alignment
  IdSize = 24
};

/// Id of the bundle is IdSize bytes. Can and should be used as a POD type
struct Id
{
  char blob[ IdSize ];

  bool operator == ( Id const & other ) const
  { return memcmp( blob, other.blob, sizeof( blob ) ) == 0; }
  bool operator != ( Id const & other ) const
  { return ! operator == ( other ); }
  bool operator < ( Id const & other ) const
  { return memcmp( blob, other.blob, sizeof( blob ) ) < 0; }
};

STATIC_ASSERT( sizeof( Id ) == IdSize );

/// Reads the bundle and allows accessing chunks
class Reader: NoCopy
{
  BundleInfo info;
  BundleFileHeader header;
  /// Unpacked payload
  string payload;
  /// Maps chunk id blob to its contents and size
  typedef map< string, pair< char const *, size_t > > Chunks;
  Chunks chunks;

public:
  DEF_EX( Ex, "Bundle reader exception", std::exception )
  DEF_EX( exBundleReadFailed, "Bundle read failed", Ex )
  DEF_EX( exUnsupportedVersion, "Unsupported version of the index file format", Ex )
  DEF_EX( exTooMuchData, "More data than expected in a bundle", Ex )
  DEF_EX( exDuplicateChunks, "Chunks with the same id found in a bundle", Ex )

  Reader( string const & fileName, EncryptionKey const & key,
      bool keepStream = false );

  /// Reads the chunk into chunkData and returns true, or returns false if there
  /// was no such chunk in the bundle. chunkData may be enlarged but won't
  /// be shrunk. The size of the actual chunk would be stored in chunkDataSize
  bool get( string const & chunkId, string & chunkData, size_t & chunkDataSize );
  BundleInfo getBundleInfo()
  { return info; }
  BundleFileHeader getBundleHeader()
  { return header; }
  string getPayload()
  { return payload; }

  sptr< EncryptedFile::InputStream > is;
};

/// Creates a bundle by adding chunks to it until it's full, then compressing
/// it and writing out to disk
class Creator
{
  BundleInfo info;
  string payload;

public:
  DEF_EX( Ex, "Bundle creator exception", std::exception )
  DEF_EX( exBundleWriteFailed, "Bundle write failed", Ex )

  /// Adds a chunk with the given id
  void addChunk( string const & chunkId, void const * data, size_t size );

  /// Returns the number of bytes comprising all chunk bodies so far
  size_t getPayloadSize() const
  { return payload.size(); }

  /// Compresses and writes the bundle to the given file. The operation is
  /// time-consuming - calling this function from a worker thread could be
  /// warranted
  void write( Config const &, string const & fileName, EncryptionKey const & );
  void write( string const & fileName, EncryptionKey const &,
      Bundle::Reader & reader );

  /// Returns the current BundleInfo record - this is used for index files
  BundleInfo const & getCurrentBundleInfo() const
  { return info; }
};

/// Generates a full file name for a bundle with the given id. If createDirs
/// is true, any intermediate directories will be created if they don't exist
/// already
string generateFileName( Id const &, string const & bundlesDir,
                         bool createDirs );
}

#endif