1 // distribution boxbackup-0.11_trunk_2979 (svn version: 2979)
2 // Box Backup, http://www.boxbackup.org/
3 //
4 // Copyright (c) 2003-2010, Ben Summers and contributors.
5 // All rights reserved.
6 //
7 // Note that this project uses mixed licensing. Any file with this license
8 // attached, or where the code LICENSE-GPL appears on the first line, falls
9 // under the "Box Backup GPL" license. See the file COPYING.txt for more
10 // information about this license.
11 //
12 // ---------------------------------------------------------------------
13 // This program is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU General Public License
15 // as published by the Free Software Foundation; either version 2
16 // of the License, or (at your option) any later version.
17 //
18 // This program is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with this program; if not, write to the Free Software
25 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26 //
27 // [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC4]
28 //
29 // As a special exception to the GPLv2, the Box Backup Project gives
30 // permission to link any code falling under this license (the Box Backup
31 // GPL) with any software that can be downloaded from
32 // the OpenSSL website [http://www.openssl.org] under either the
33 // "OpenSSL License" or the "Original SSLeay License", and to distribute
34 // the linked executables under the terms of the "Box Backup GPL" license.
35 //
36 // As a special exception to the GPLv2, the Box Backup Project gives
37 // permission to link any code falling under this license (the Box Backup
38 // GPL) with any version of Microsoft's Volume Shadow Copy Service 7.2 SDK
39 // or Microsoft Windows Software Development Kit (SDK), including
40 // vssapi.lib, that can be downloaded from the Microsoft website
41 // [*.microsoft.com], and to distribute the linked executables under the
42 // terms of the "Box Backup GPL" license.
43 // --------------------------------------------------------------------------
44 //
45 // File
46 //		Name:    BackupStoreDirectory.h
47 //		Purpose: Representation of a backup directory
48 //		Created: 2003/08/26
49 //
50 // --------------------------------------------------------------------------
51 
52 #ifndef BACKUPSTOREDIRECTORY__H
53 #define BACKUPSTOREDIRECTORY__H
54 
55 #include <string>
56 #include <vector>
57 
58 #include "BackupStoreFilenameClear.h"
59 #include "StreamableMemBlock.h"
60 #include "BoxTime.h"
61 
62 class IOStream;
63 
64 // --------------------------------------------------------------------------
65 //
66 // Class
67 //		Name:    BackupStoreDirectory
68 //		Purpose: In memory representation of a directory
69 //		Created: 2003/08/26
70 //
71 // --------------------------------------------------------------------------
72 class BackupStoreDirectory
73 {
74 public:
75 	BackupStoreDirectory();
76 	BackupStoreDirectory(int64_t ObjectID, int64_t ContainerID);
77 private:
78 	// Copying not allowed
79 	BackupStoreDirectory(const BackupStoreDirectory &rToCopy);
80 public:
81 	~BackupStoreDirectory();
82 
83 	class Entry
84 	{
85 	public:
86 		friend class BackupStoreDirectory;
87 
88 		Entry();
89 		~Entry();
90 		Entry(const Entry &rToCopy);
91 		Entry(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags, uint64_t AttributesHash);
92 
93 		void ReadFromStream(IOStream &rStream, int Timeout);
94 		void WriteToStream(IOStream &rStream) const;
95 
GetName()96 		const BackupStoreFilename &GetName() const {return mName;}
GetModificationTime()97 		box_time_t GetModificationTime() const {return mModificationTime;}
GetObjectID()98 		int64_t GetObjectID() const {return mObjectID;}
GetSizeInBlocks()99 		int64_t GetSizeInBlocks() const {return mSizeInBlocks;}
GetFlags()100 		int16_t GetFlags() const {return mFlags;}
AddFlags(int16_t Flags)101 		void AddFlags(int16_t Flags) {mFlags |= Flags;}
RemoveFlags(int16_t Flags)102 		void RemoveFlags(int16_t Flags) {mFlags &= ~Flags;}
103 
104 		// Some things can be changed
SetName(const BackupStoreFilename & rNewName)105 		void SetName(const BackupStoreFilename &rNewName) {mName = rNewName;}
SetSizeInBlocks(int64_t SizeInBlocks)106 		void SetSizeInBlocks(int64_t SizeInBlocks) {mSizeInBlocks = SizeInBlocks;}
107 
108 		// Attributes
HasAttributes()109 		bool HasAttributes() const {return !mAttributes.IsEmpty();}
SetAttributes(const StreamableMemBlock & rAttr,uint64_t AttributesHash)110 		void SetAttributes(const StreamableMemBlock &rAttr, uint64_t AttributesHash) {mAttributes.Set(rAttr); mAttributesHash = AttributesHash;}
GetAttributes()111 		const StreamableMemBlock &GetAttributes() const {return mAttributes;}
GetAttributesHash()112 		uint64_t GetAttributesHash() const {return mAttributesHash;}
113 
114 		// Marks
115 		// The lowest mark number a version of a file of this name has ever had
GetMinMarkNumber()116 		uint32_t GetMinMarkNumber() const {return mMinMarkNumber;}
117 		// The mark number on this file
GetMarkNumber()118 		uint32_t GetMarkNumber() const {return mMarkNumber;}
119 
120 		// Make sure these flags are synced with those in backupprocotol.txt
121 		// ListDirectory command
122 		enum
123 		{
124 			Flags_INCLUDE_EVERYTHING 	= -1,
125 			Flags_EXCLUDE_NOTHING 		= 0,
126 			Flags_EXCLUDE_EVERYTHING	= 31,	// make sure this is kept as sum of ones below!
127 			Flags_File					= 1,
128 			Flags_Dir					= 2,
129 			Flags_Deleted				= 4,
130 			Flags_OldVersion			= 8,
131 			Flags_RemoveASAP			= 16	// if this flag is set, housekeeping will remove it as it is marked Deleted or OldVersion
132 		};
133 		// characters for textual listing of files -- see bbackupquery/BackupQueries
134 		#define BACKUPSTOREDIRECTORY_ENTRY_FLAGS_DISPLAY_NAMES "fdXoR"
135 
136 		// convenience methods
IsDir()137 		bool inline IsDir()
138 		{
139 			return GetFlags() & Flags_Dir;
140 		}
IsFile()141 		bool inline IsFile()
142 		{
143 			return GetFlags() & Flags_File;
144 		}
IsOld()145 		bool inline IsOld()
146 		{
147 			return GetFlags() & Flags_OldVersion;
148 		}
IsDeleted()149 		bool inline IsDeleted()
150 		{
151 			return GetFlags() & Flags_Deleted;
152 		}
MatchesFlags(int16_t FlagsMustBeSet,int16_t FlagsNotToBeSet)153 		bool inline MatchesFlags(int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet)
154 		{
155 			return ((FlagsMustBeSet == Flags_INCLUDE_EVERYTHING) || ((mFlags & FlagsMustBeSet) == FlagsMustBeSet))
156 				&& ((mFlags & FlagsNotToBeSet) == 0);
157 		};
158 
159 		// Get dependency info
160 		// new version this depends on
GetDependsNewer()161 		int64_t GetDependsNewer() const {return mDependsNewer;}
SetDependsNewer(int64_t ObjectID)162 		void SetDependsNewer(int64_t ObjectID) {mDependsNewer = ObjectID;}
163 		// older version which depends on this
GetDependsOlder()164 		int64_t GetDependsOlder() const {return mDependsOlder;}
SetDependsOlder(int64_t ObjectID)165 		void SetDependsOlder(int64_t ObjectID) {mDependsOlder = ObjectID;}
166 
167 		// Dependency info saving
HasDependencies()168 		bool HasDependencies() {return mDependsNewer != 0 || mDependsOlder != 0;}
169 		void ReadFromStreamDependencyInfo(IOStream &rStream, int Timeout);
170 		void WriteToStreamDependencyInfo(IOStream &rStream) const;
171 
172 	private:
173 		BackupStoreFilename	mName;
174 		box_time_t mModificationTime;
175 		int64_t mObjectID;
176 		int64_t mSizeInBlocks;
177 		int16_t mFlags;
178 		uint64_t mAttributesHash;
179 		StreamableMemBlock mAttributes;
180 		uint32_t mMinMarkNumber;
181 		uint32_t mMarkNumber;
182 
183 		uint64_t mDependsNewer;	// new version this depends on
184 		uint64_t mDependsOlder;	// older version which depends on this
185 	};
186 
187 	void ReadFromStream(IOStream &rStream, int Timeout);
188 	void WriteToStream(IOStream &rStream,
189 			int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING,
190 			int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING,
191 			bool StreamAttributes = true, bool StreamDependencyInfo = true) const;
192 
193 	Entry *AddEntry(const Entry &rEntryToCopy);
194 	Entry *AddEntry(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags, box_time_t AttributesModTime);
195 	void DeleteEntry(int64_t ObjectID);
196 	Entry *FindEntryByID(int64_t ObjectID) const;
197 
GetObjectID()198 	int64_t GetObjectID() const {return mObjectID;}
GetContainerID()199 	int64_t GetContainerID() const {return mContainerID;}
200 
201 	// Need to be able to update the container ID when moving objects
SetContainerID(int64_t ContainerID)202 	void SetContainerID(int64_t ContainerID) {mContainerID = ContainerID;}
203 
204 	// Purely for use of server -- not serialised into streams
GetRevisionID()205 	int64_t GetRevisionID() const {return mRevisionID;}
SetRevisionID(int64_t RevisionID)206 	void SetRevisionID(int64_t RevisionID) {mRevisionID = RevisionID;}
207 
GetNumberOfEntries()208 	unsigned int GetNumberOfEntries() const {return mEntries.size();}
209 
210 	// User info -- not serialised into streams
GetUserInfo1_SizeInBlocks()211 	int64_t GetUserInfo1_SizeInBlocks() const {return mUserInfo1;}
SetUserInfo1_SizeInBlocks(int64_t UserInfo1)212 	void SetUserInfo1_SizeInBlocks(int64_t UserInfo1) {mUserInfo1 = UserInfo1;}
213 
214 	// Attributes
HasAttributes()215 	bool HasAttributes() const {return !mAttributes.IsEmpty();}
SetAttributes(const StreamableMemBlock & rAttr,box_time_t AttributesModTime)216 	void SetAttributes(const StreamableMemBlock &rAttr, box_time_t AttributesModTime) {mAttributes.Set(rAttr); mAttributesModTime = AttributesModTime;}
GetAttributes()217 	const StreamableMemBlock &GetAttributes() const {return mAttributes;}
GetAttributesModTime()218 	box_time_t GetAttributesModTime() const {return mAttributesModTime;}
219 
220 	class Iterator
221 	{
222 	public:
Iterator(const BackupStoreDirectory & rDir)223 		Iterator(const BackupStoreDirectory &rDir)
224 			: mrDir(rDir), i(rDir.mEntries.begin())
225 		{
226 		}
227 
228 		BackupStoreDirectory::Entry *Next(int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING)
229 		{
230 			// Skip over things which don't match the required flags
231 			while(i != mrDir.mEntries.end() && !(*i)->MatchesFlags(FlagsMustBeSet, FlagsNotToBeSet))
232 			{
233 				++i;
234 			}
235 			// Not the last one?
236 			if(i == mrDir.mEntries.end())
237 			{
238 				return 0;
239 			}
240 			// Return entry, and increment
241 			return (*(i++));
242 		}
243 
244 		// WARNING: This function is really very inefficient.
245 		// Only use when you want to look up ONE filename, not in a loop looking up lots.
246 		// In a looping situation, cache the decrypted filenames in another memory structure.
247 		BackupStoreDirectory::Entry *FindMatchingClearName(const BackupStoreFilenameClear &rFilename, int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING)
248 		{
249 			// Skip over things which don't match the required flags or filename
250 			while( (i != mrDir.mEntries.end())
251 				&& ( (!(*i)->MatchesFlags(FlagsMustBeSet, FlagsNotToBeSet))
252 					|| (BackupStoreFilenameClear((*i)->GetName()).GetClearFilename() != rFilename.GetClearFilename()) ) )
253 			{
254 				++i;
255 			}
256 			// Not the last one?
257 			if(i == mrDir.mEntries.end())
258 			{
259 				return 0;
260 			}
261 			// Return entry, and increment
262 			return (*(i++));
263 		}
264 
265 	private:
266 		const BackupStoreDirectory &mrDir;
267 		std::vector<Entry*>::const_iterator i;
268 	};
269 
270 	friend class Iterator;
271 
272 	class ReverseIterator
273 	{
274 	public:
ReverseIterator(const BackupStoreDirectory & rDir)275 		ReverseIterator(const BackupStoreDirectory &rDir)
276 			: mrDir(rDir), i(rDir.mEntries.rbegin())
277 		{
278 		}
279 
280 		BackupStoreDirectory::Entry *Next(int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING)
281 		{
282 			// Skip over things which don't match the required flags
283 			while(i != mrDir.mEntries.rend() && !(*i)->MatchesFlags(FlagsMustBeSet, FlagsNotToBeSet))
284 			{
285 				++i;
286 			}
287 			// Not the last one?
288 			if(i == mrDir.mEntries.rend())
289 			{
290 				return 0;
291 			}
292 			// Return entry, and increment
293 			return (*(i++));
294 		}
295 
296 	private:
297 		const BackupStoreDirectory &mrDir;
298 		std::vector<Entry*>::const_reverse_iterator i;
299 	};
300 
301 	friend class ReverseIterator;
302 
303 	// For recovery of the store
304 	// Implemented in BackupStoreCheck2.cpp
305 	bool CheckAndFix();
306 	void AddUnattactedObject(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags);
307 	bool NameInUse(const BackupStoreFilename &rName);
308 	// Don't use these functions in normal code!
309 
310 	// For testing
TESTONLY_SetObjectID(int64_t ObjectID)311 	void TESTONLY_SetObjectID(int64_t ObjectID) {mObjectID = ObjectID;}
312 
313 	// Debug and diagonistics
314 	void Dump(void *clibFileHandle, bool ToTrace); // first arg is FILE *, but avoid including stdio.h everywhere
315 
316 private:
317 	int64_t mRevisionID;
318 	int64_t mObjectID;
319 	int64_t mContainerID;
320 	std::vector<Entry*> mEntries;
321 	box_time_t mAttributesModTime;
322 	StreamableMemBlock mAttributes;
323 	int64_t mUserInfo1;
324 };
325 
326 #endif // BACKUPSTOREDIRECTORY__H
327 
328