1 /* $Id: mkimage.hh,v 1.3 2004/09/12 21:08:28 atterer Exp $ -*- C++ -*-
3 |_) /| Copyright (C) 2001-2002 | richard@
4 | \/¯| Richard Atterer | atterer.org
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2. See
8 the file COPYING for details.
12 Create image from template / merge new files into image.tmp
29 #include <sha256sum.hh>
31 #include <serialize.hh>
32 //______________________________________________________________________
34 /** Errors thrown by the JigdoDesc code */
35 struct JigdoDescError : Error {
36 explicit JigdoDescError(const string& m) : Error(m) { }
37 explicit JigdoDescError(const char* m) : Error(m) { }
40 /** Entry in a DESC section of a jigdo template. This definition is
41 used both for an abstract base class and as a namespace for child
45 /** Types of entries in a description section */
47 OBSOLETE_IMAGE_INFO = 1,
49 OBSOLETE_MATCHED_FILE = 3,
50 OBSOLETE_WRITTEN_FILE = 4,
54 IMAGE_INFO_SHA256 = 8,
55 MATCHED_FILE_SHA256 = 9,
56 WRITTEN_FILE_SHA256 = 10
58 class ProgressReporter;
59 //____________________
61 virtual bool operator==(const JigdoDesc& x) const = 0;
62 inline bool operator!=(const JigdoDesc& x) const { return !(*this == x); }
63 virtual ~JigdoDesc() = 0;
65 /** Entry type of JigdoDesc child class */
66 virtual Type type() const = 0;
67 /** Output human-readable summary */
68 virtual ostream& put(ostream& s) const = 0;
69 /** Size of image area or whole image */
70 virtual uint64 size() const = 0;
72 /** There are no virtual templates, so this wouldn't work:<code>
73 template<class Iterator>
74 virtual Iterator serialize(Iterator i) const; </code> */
75 virtual size_t serialSizeOf() const = 0;
77 /** Check whether the file is a .template file, i.e. has the
78 appropriate ASCII header */
79 static bool isTemplate(bistream& file);
80 /** Assuming that a DESC section is at the end of a file, set the
81 file pointer to the start of the section, allowing you to call
82 read() immediately afterwards. */
83 static void seekFromEnd(bistream& file);
84 /** Create image file from template and files (via JigdoCache) */
85 static int makeImage(JigdoCache* cache, const string& imageFile,
86 const string& imageTmpFile, const string& templFile,
87 bistream* templ, const bool optForce,
88 ProgressReporter& pr = noReport, size_t readAmnt = 128U*1024,
89 const bool optMkImageCheck = true);
90 /** Return list of MD5sums of files that still need to be copied to
91 the image to complete it. Reads info from tmp file or (if
92 imageTmpFile.empty() or error opening tmp file) outputs complete
93 list from template. */
94 static int listMissingMD5(set<MD5>& result, const string& imageTmpFile,
95 const string& templFile, bistream* templ, ProgressReporter& reporter);
96 /** Return list of SHA256sums of files that still need to be copied to
97 the image to complete it. Reads info from tmp file or (if
98 imageTmpFile.empty() or error opening tmp file) outputs complete
99 list from template. */
100 static int listMissingSHA256(set<SHA256>& result, const string& imageTmpFile,
101 const string& templFile, bistream* templ, ProgressReporter& reporter);
104 class ImageInfoSHA256;
106 class MatchedFileMD5;
107 class MatchedFileSHA256;
108 class WrittenFileMD5;
109 class WrittenFileSHA256;
112 static ProgressReporter noReport;
115 inline ostream& operator<<(ostream& s, JigdoDesc& jd) { return jd.put(s); }
116 //______________________________________________________________________
118 /** Information about the image file */
119 class JigdoDesc::ImageInfoMD5 : public JigdoDesc {
121 inline ImageInfoMD5(uint64 s, const MD5& m, size_t b);
122 inline ImageInfoMD5(uint64 s, const MD5Sum& m, size_t b);
123 inline bool operator==(const JigdoDesc& x) const;
124 Type type() const { return IMAGE_INFO_MD5; }
125 uint64 size() const { return sizeVal; }
126 const MD5& md5() const { return md5Val; }
127 size_t blockLength() const { return blockLengthVal; }
128 // Default dtor, operator==
129 virtual ostream& put(ostream& s) const;
131 template<class Iterator>
132 inline Iterator serialize(Iterator i) const;
133 inline size_t serialSizeOf() const;
138 size_t blockLengthVal;
140 //________________________________________
142 /** Information about the image file */
143 class JigdoDesc::ImageInfoSHA256 : public JigdoDesc {
145 inline ImageInfoSHA256(uint64 s, const SHA256& m, size_t b);
146 inline ImageInfoSHA256(uint64 s, const SHA256Sum& m, size_t b);
147 inline bool operator==(const JigdoDesc& x) const;
148 Type type() const { return IMAGE_INFO_SHA256; }
149 uint64 size() const { return sizeVal; }
150 const SHA256& sha256() const { return sha256Val; }
151 size_t blockLength() const { return blockLengthVal; }
152 // Default dtor, operator==
153 virtual ostream& put(ostream& s) const;
155 template<class Iterator>
156 inline Iterator serialize(Iterator i) const;
157 inline size_t serialSizeOf() const;
162 size_t blockLengthVal;
164 //________________________________________
166 /** Info about data that was not matched by any input file, i.e.
167 that is included in the template data verbatim */
168 class JigdoDesc::UnmatchedData : public JigdoDesc {
170 UnmatchedData(uint64 o, uint64 s) : offsetVal(o), sizeVal(s) { }
171 inline bool operator==(const JigdoDesc& x) const;
172 Type type() const { return UNMATCHED_DATA; }
173 uint64 offset() const { return offsetVal; }
174 uint64 size() const { return sizeVal; }
175 void resize(uint64 s) { sizeVal = s; }
176 // Default dtor, operator==
177 virtual ostream& put(ostream& s) const;
179 template<class Iterator>
180 inline Iterator serialize(Iterator i) const;
181 inline size_t serialSizeOf() const;
184 uint64 offsetVal; // Offset in image
187 //________________________________________
189 /** Info about data that *was* matched by an input file */
190 class JigdoDesc::MatchedFileMD5 : public JigdoDesc {
192 inline MatchedFileMD5(uint64 o, uint64 s, const RsyncSum64& r, const MD5& m);
193 inline MatchedFileMD5(uint64 o, uint64 s, const RsyncSum64& r,
195 inline bool operator==(const JigdoDesc& x) const;
196 Type type() const { return MATCHED_FILE; }
197 uint64 offset() const { return offsetVal; }
198 uint64 size() const { return sizeVal; }
199 const MD5& md5() const { return md5Val; }
200 const RsyncSum64& rsync() const { return rsyncVal; }
201 // Default dtor, operator==
202 virtual ostream& put(ostream& s) const;
204 template<class Iterator>
205 inline Iterator serialize(Iterator i) const;
206 inline size_t serialSizeOf() const;
209 uint64 offsetVal; // Offset in image
214 //________________________________________
216 /** Like MatchedFileMD5 - used only in .tmp files to express that the
217 file data was successfully written to the image. NB: Because this
218 derives from MatchedFileMD5 and because of the implementation of
219 JigdoDesc::operator==, MatchedFileMD5's and WrittenFileMD5's will
220 compare equal if their data fields are identical. */
221 class JigdoDesc::WrittenFileMD5 : public MatchedFileMD5 {
223 WrittenFileMD5(uint64 o, uint64 s, const RsyncSum64& r, const MD5& m)
224 : MatchedFileMD5(o, s, r, m) { }
225 // Implicit cast to allow MatchedFileMD5 and WrittenFileMD5 to compare equal
226 inline bool operator==(const JigdoDesc& x) const;
227 Type type() const { return WRITTEN_FILE; }
228 virtual ostream& put(ostream& s) const;
230 template<class Iterator>
231 inline Iterator serialize(Iterator i) const;
232 inline size_t serialSizeOf() const;
234 //______________________________________________________________________
236 /** Info about data that *was* matched by an input file */
237 class JigdoDesc::MatchedFileSHA256 : public JigdoDesc {
239 inline MatchedFileSHA256(uint64 o, uint64 s, const RsyncSum64& r, const SHA256& m);
240 inline MatchedFileSHA256(uint64 o, uint64 s, const RsyncSum64& r,
242 inline bool operator==(const JigdoDesc& x) const;
243 Type type() const { return MATCHED_FILE_SHA256; }
244 uint64 offset() const { return offsetVal; }
245 uint64 size() const { return sizeVal; }
246 const SHA256& sha256() const { return sha256Val; }
247 const RsyncSum64& rsync() const { return rsyncVal; }
248 // Default dtor, operator==
249 virtual ostream& put(ostream& s) const;
251 template<class Iterator>
252 inline Iterator serialize(Iterator i) const;
253 inline size_t serialSizeOf() const;
256 uint64 offsetVal; // Offset in image
261 //________________________________________
263 /** Like MatchedFileSHA256 - used only in .tmp files to express that the
264 file data was successfully written to the image. NB: Because this
265 derives from MatchedFileSHA256 and because of the implementation of
266 JigdoDesc::operator==, MatchedFileSHA256's and WrittenFileSHA256's will
267 compare equal if their data fields are identical. */
268 class JigdoDesc::WrittenFileSHA256 : public MatchedFileSHA256 {
270 WrittenFileSHA256(uint64 o, uint64 s, const RsyncSum64& r, const SHA256& m)
271 : MatchedFileSHA256(o, s, r, m) { }
272 // Implicit cast to allow MatchedFileSHA256 and WrittenFileSHA256 to compare equal
273 inline bool operator==(const JigdoDesc& x) const;
274 Type type() const { return WRITTEN_FILE_SHA256; }
275 virtual ostream& put(ostream& s) const;
277 template<class Iterator>
278 inline Iterator serialize(Iterator i) const;
279 inline size_t serialSizeOf() const;
281 //______________________________________________________________________
283 /** Class allowing JigdoDesc to convey information back to the caller.
284 The default versions of the methods do nothing at all (except for
285 error(), which prints the error to cerr) - you need to supply an
286 object of a derived class to functions to get called back. */
287 class JigdoDesc::ProgressReporter {
289 virtual ~ProgressReporter() { }
290 /** General-purpose error reporting. */
291 virtual void error(const string& message);
292 /** Like error(), but for purely informational messages. */
293 virtual void info(const string& message);
294 /** Called when the output image (or a temporary file) is being
295 written to. It holds that written==imgOff and
296 totalToWrite==imgSize, *except* when additional files are merged
297 into an already existing temporary file.
298 @param written Number of bytes written so far
299 @param totalToWrite Value of 'written' at end of write operation
300 @param imgOff Current offset in image
301 @param imgSize Total size of output image */
302 virtual void writingImage(uint64 written, uint64 totalToWrite,
303 uint64 imgOff, uint64 imgSize);
305 //______________________________________________________________________
307 /** Container for JidoDesc objects. Is mostly a vector<JidoDesc*>, but
308 deletes elements when destroyed. However, when removing elements,
309 resizing the JigdoDescVec etc., the elements are *not* deleted
311 class JigdoDescVec : public vector<JigdoDesc*> {
313 JigdoDescVec() : vector<JigdoDesc*>() { }
314 inline ~JigdoDescVec();
316 /** Read JigdoDescs from a template file into *this. *this is
317 clear()ed first. File pointer must be at start of first entry;
318 the "DESC" must have been read already. If error is thrown,
319 position of file pointer is undefined. A type 1 (IMAGE_INFO_MD5)
320 will end up at this->back(). */
321 bistream& get(bistream& file);
323 /** Write a DESC section to a binary stream. Note that there should
324 not be two contiguous Unmatched regions - this is not checked.
325 Similarly, the length of the ImageInfo* part must match the
326 accumulated lengths of the other parts. */
327 bostream& put(bostream& file, MD5Sum* md = 0, SHA256Sum* sd = 0, int checksumChoice = 0) const;
329 /** List contents of a JigdoDescVec to a stream in human-readable format. */
330 void list(ostream& s) throw();
332 // Disallow copying (too inefficient). Use swap() instead.
333 inline JigdoDescVec& operator=(const JigdoDescVec&);
336 inline void swap(JigdoDescVec& x, JigdoDescVec& y) { x.swap(y); }
338 //======================================================================
340 JigdoDesc::ImageInfoMD5::ImageInfoMD5(uint64 s, const MD5& m, size_t b)
341 : sizeVal(s), md5Val(m), blockLengthVal(b) { }
342 JigdoDesc::ImageInfoMD5::ImageInfoMD5(uint64 s, const MD5Sum& m, size_t b)
343 : sizeVal(s), md5Val(m), blockLengthVal(b) { }
344 JigdoDesc::ImageInfoSHA256::ImageInfoSHA256(uint64 s, const SHA256& m, size_t b)
345 : sizeVal(s), sha256Val(m), blockLengthVal(b) { }
346 JigdoDesc::ImageInfoSHA256::ImageInfoSHA256(uint64 s, const SHA256Sum& m, size_t b)
347 : sizeVal(s), sha256Val(m), blockLengthVal(b) { }
349 JigdoDesc::MatchedFileMD5::MatchedFileMD5(uint64 o, uint64 s, const RsyncSum64& r,
351 : offsetVal(o), sizeVal(s), rsyncVal(r), md5Val(m) { }
352 JigdoDesc::MatchedFileSHA256::MatchedFileSHA256(uint64 o, uint64 s, const RsyncSum64& r,
354 : offsetVal(o), sizeVal(s), rsyncVal(r), sha256Val(m) { }
355 JigdoDesc::MatchedFileMD5::MatchedFileMD5(uint64 o, uint64 s, const RsyncSum64& r,
357 : offsetVal(o), sizeVal(s), rsyncVal(r), md5Val(m) { }
358 JigdoDesc::MatchedFileSHA256::MatchedFileSHA256(uint64 o, uint64 s, const RsyncSum64& r,
360 : offsetVal(o), sizeVal(s), rsyncVal(r), sha256Val(m) { }
362 //________________________________________
364 bool JigdoDesc::ImageInfoMD5::operator==(const JigdoDesc& x) const {
365 const ImageInfoMD5* i = dynamic_cast<const ImageInfoMD5*>(&x);
366 if (i == 0) return false;
367 else return size() == i->size() && md5() == i->md5();
370 bool JigdoDesc::ImageInfoSHA256::operator==(const JigdoDesc& x) const {
371 const ImageInfoSHA256* i = dynamic_cast<const ImageInfoSHA256*>(&x);
372 if (i == 0) return false;
373 else return size() == i->size() && sha256() == i->sha256();
376 bool JigdoDesc::UnmatchedData::operator==(const JigdoDesc& x) const {
377 const UnmatchedData* u = dynamic_cast<const UnmatchedData*>(&x);
378 if (u == 0) return false;
379 else return size() == u->size();
382 bool JigdoDesc::MatchedFileMD5::operator==(const JigdoDesc& x) const {
383 const MatchedFileMD5* m = dynamic_cast<const MatchedFileMD5*>(&x);
384 if (m == 0) return false;
385 else return offset() == m->offset() && size() == m->size()
386 && md5() == m->md5();
389 bool JigdoDesc::MatchedFileSHA256::operator==(const JigdoDesc& x) const {
390 const MatchedFileSHA256* m = dynamic_cast<const MatchedFileSHA256*>(&x);
391 if (m == 0) return false;
392 else return offset() == m->offset() && size() == m->size()
393 && sha256() == m->sha256();
396 bool JigdoDesc::WrittenFileMD5::operator==(const JigdoDesc& x) const {
397 // NB MatchedFileMD5 and WrittenFileMD5 considered equal!
398 const MatchedFileMD5* m = dynamic_cast<const MatchedFileMD5*>(&x);
399 if (m == 0) return false;
400 else return offset() == m->offset() && size() == m->size()
401 && md5() == m->md5();
404 bool JigdoDesc::WrittenFileSHA256::operator==(const JigdoDesc& x) const {
405 // NB MatchedFileSHA256 and WrittenFileSHA256 considered equal!
406 const MatchedFileSHA256* m = dynamic_cast<const MatchedFileSHA256*>(&x);
407 if (m == 0) return false;
408 else return offset() == m->offset() && size() == m->size()
409 && sha256() == m->sha256();
411 //________________________________________
413 inline bistream& operator>>(bistream& s, JigdoDescVec& v) {
417 inline bostream& operator<<(bostream& s, JigdoDescVec& v) {
421 JigdoDescVec::~JigdoDescVec() {
422 for (iterator i = begin(), e = end(); i != e; ++i) delete *i;
424 //________________________________________
426 template<class Iterator>
427 Iterator JigdoDesc::ImageInfoMD5::serialize(Iterator i) const {
428 i = serialize1(IMAGE_INFO_MD5, i);
429 i = serialize6(size(), i);
430 i = ::serialize(md5(), i);
431 i = serialize4(blockLength(), i);
434 size_t JigdoDesc::ImageInfoMD5::serialSizeOf() const { return 1 + 6 + 16 + 4; }
436 template<class Iterator>
437 Iterator JigdoDesc::ImageInfoSHA256::serialize(Iterator i) const {
438 i = serialize1(IMAGE_INFO_SHA256, i);
439 i = serialize6(size(), i);
440 i = ::serialize(sha256(), i);
441 i = serialize4(blockLength(), i);
444 size_t JigdoDesc::ImageInfoSHA256::serialSizeOf() const { return 1 + 6 + 32 + 4; }
446 template<class Iterator>
447 Iterator JigdoDesc::UnmatchedData::serialize(Iterator i) const {
448 i = serialize1(UNMATCHED_DATA, i);
449 i = serialize6(size(), i);
452 size_t JigdoDesc::UnmatchedData::serialSizeOf() const { return 1 + 6; }
454 template<class Iterator>
455 Iterator JigdoDesc::MatchedFileMD5::serialize(Iterator i) const {
456 i = serialize1(MATCHED_FILE, i);
457 i = serialize6(size(), i);
458 i = ::serialize(rsync(), i);
459 i = ::serialize(md5(), i);
462 size_t JigdoDesc::MatchedFileMD5::serialSizeOf() const { return 1 + 6 + 8 + 16;}
464 template<class Iterator>
465 Iterator JigdoDesc::MatchedFileSHA256::serialize(Iterator i) const {
466 i = serialize1(MATCHED_FILE_SHA256, i);
467 i = serialize6(size(), i);
468 i = ::serialize(rsync(), i);
469 i = ::serialize(sha256(), i);
472 size_t JigdoDesc::MatchedFileSHA256::serialSizeOf() const { return 1 + 6 + 8 + 32;}
474 template<class Iterator>
475 Iterator JigdoDesc::WrittenFileMD5::serialize(Iterator i) const {
476 i = serialize1(WRITTEN_FILE, i);
477 i = serialize6(size(), i);
478 i = ::serialize(rsync(), i);
479 i = ::serialize(md5(), i);
482 size_t JigdoDesc::WrittenFileMD5::serialSizeOf() const { return 1 + 6 + 8 + 16;}
484 template<class Iterator>
485 Iterator JigdoDesc::WrittenFileSHA256::serialize(Iterator i) const {
486 i = serialize1(WRITTEN_FILE_SHA256, i);
487 i = serialize6(size(), i);
488 i = ::serialize(rsync(), i);
489 i = ::serialize(sha256(), i);
492 size_t JigdoDesc::WrittenFileSHA256::serialSizeOf() const { return 1 + 6 + 8 + 32;}