// test the sequence value
if ( test_sequence != sequence )
{
- DefaultLogSink().Error("IntegrityPack failure: sequence is %lu, expecting %lu.\n", test_sequence, sequence);
+ DefaultLogSink().Error("IntegrityPack failure: sequence is %u, expecting %u.\n", test_sequence, sequence);
return RESULT_HMACFAIL;
}
fprintf(stream, "SIZ: \n");
fprintf(stream, " Rsize: %hu\n", Rsize());
- fprintf(stream, " Xsize: %u\n", Xsize());
- fprintf(stream, " Ysize: %u\n", Xsize());
- fprintf(stream, " XOsize: %u\n", XOsize());
- fprintf(stream, " YOsize: %u\n", XOsize());
- fprintf(stream, " XTsize: %u\n", XTsize());
- fprintf(stream, " YTsize: %u\n", XTsize());
- fprintf(stream, "XTOsize: %u\n", XTOsize());
- fprintf(stream, "YTOsize: %u\n", YTOsize());
- fprintf(stream, " Csize: %u\n", Csize());
+ fprintf(stream, " Xsize: %u\n", Xsize());
+ fprintf(stream, " Ysize: %u\n", Xsize());
+ fprintf(stream, " XOsize: %u\n", XOsize());
+ fprintf(stream, " YOsize: %u\n", XOsize());
+ fprintf(stream, " XTsize: %u\n", XTsize());
+ fprintf(stream, " YTsize: %u\n", XTsize());
+ fprintf(stream, "XTOsize: %u\n", XTOsize());
+ fprintf(stream, "YTOsize: %u\n", YTOsize());
+ fprintf(stream, " Csize: %u\n", Csize());
if ( Csize() > 0 )
{
UL(const byte_t* value) : Kumu::Identifier<SMPTE_UL_LENGTH>(value) {}
virtual ~UL() {}
- const UL& operator=(const UL& rhs) {
- if ( m_HasValue = rhs.m_HasValue )
- memcpy(m_Value, rhs.m_Value, SMPTE_UL_LENGTH);
- return *this;
- }
-
const char* EncodeString(char* str_buf, ui32_t buf_len) const;
};
UMID(const byte_t* value) : Kumu::Identifier<SMPTE_UMID_LENGTH>(value) {}
virtual ~UMID() {}
- const UMID& operator=(const UMID& rhs) {
- if ( m_HasValue = rhs.m_HasValue )
- memcpy(m_Value, rhs.m_Value, SMPTE_UMID_LENGTH);
- return *this;
- }
-
void MakeUMID(int Type);
void MakeUMID(int Type, const UUID& ID);
const char* EncodeString(char* str_buf, ui32_t buf_len) const;
//
void
-Kumu::GenRandomValue(SymmetricKey& ID)
+Kumu::GenRandomValue(SymmetricKey& Key)
{
byte_t tmp_buf[SymmetricKey_Length];
FortunaRNG RNG;
RNG.FillRandom(tmp_buf, SymmetricKey_Length);
- ID.Set(tmp_buf);
+ Key.Set(tmp_buf);
}
bool
Kumu::Timestamp::DecodeString(const char* datestr)
{
+ Timestamp TmpStamp;
+
if ( ! ( isdigit(datestr[0]) && isdigit(datestr[1]) && isdigit(datestr[2]) && isdigit(datestr[3]) )
|| datestr[4] != '-'
|| ! ( isdigit(datestr[5]) && isdigit(datestr[6]) )
|| datestr[7] != '-'
- || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) )
- || datestr[10] != 'T'
- || ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
- || datestr[13] != ':'
- || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) )
- || datestr[16] != ':'
- || ! ( isdigit(datestr[17]) && isdigit(datestr[18]) )
- || ! ( datestr[19] == '-' || datestr[19] == '+' )
- || ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
- || datestr[22] != ':'
- || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
+ || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) ) )
return false;
- // TODO -- test this!
- Year = atoi(datestr);
- Month = atoi(datestr + 5);
- Day = atoi(datestr + 8);
- Hour = atoi(datestr + 11);
- Minute = atoi(datestr + 14);
- Second = atoi(datestr + 17);
+ TmpStamp.Year = atoi(datestr);
+ TmpStamp.Month = atoi(datestr + 5);
+ TmpStamp.Day = atoi(datestr + 8);
+ TmpStamp.Hour = TmpStamp.Minute = TmpStamp.Second = 0;
+
+ if ( datestr[10] == 'T' )
+ {
+ if ( ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
+ || datestr[13] != ':'
+ || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) ) )
+ return false;
- ui32_t TZ_hh = atoi(datestr + 20);
- ui32_t TZ_mm = atoi(datestr + 23);
+ TmpStamp.Hour = atoi(datestr + 11);
+ TmpStamp.Minute = atoi(datestr + 14);
- if ( TZ_mm != 0 )
- DefaultLogSink().Error("Ignoring sub-hours timezone offset: %u\n", TZ_mm);
-
- if ( TZ_hh > 12 )
- DefaultLogSink().Error("Ignoring large timezone offset: %s\n", (datestr+19));
- else
- AddHours(TZ_hh);
+ if ( datestr[16] == ':' )
+ {
+ if ( ! ( isdigit(datestr[17]) && isdigit(datestr[18]) ) )
+ return false;
+
+ TmpStamp.Second = atoi(datestr + 17);
+ }
+ }
+
+ if ( datestr[19] == '-' || datestr[19] == '+' )
+ {
+ if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
+ || datestr[22] != ':'
+ || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
+ return false;
+
+ ui32_t TZ_hh = atoi(datestr + 20);
+ ui32_t TZ_mm = atoi(datestr + 23);
+
+ if ( TZ_mm != 0 )
+ DefaultLogSink().Error("Ignoring minutes in timezone offset: %u\n", TZ_mm);
+
+ if ( TZ_hh > 12 )
+ return false;
+
+ else
+ AddHours( (datestr[19] == '-' ? (-TZ_hh) : TZ_hh));
+ }
+
+#ifdef KM_WIN32
+ SYSTEMTIME st;
+ FILETIME ft;
+ TIMESTAMP_TO_SYSTIME(TmpStamp, &st);
+ if ( SystemTimeToFileTime(&st, &ft) == 0 )
+ return false;
+ SYSTIME_TO_TIMESTAMP(&st, *this);
+#else
+ struct tm stm;
+ TIMESTAMP_TO_TM(TmpStamp, &stm);
+ if ( timegm(&stm) == 0 )
+ return false;
+ TM_TO_TIMESTAMP(&stm, *this);
+#endif
return true;
}
template <ui32_t SIZE>
class Identifier : public IArchive
{
- const Identifier& operator=(const Identifier& rhs);
-
protected:
bool m_HasValue;
byte_t m_Value[SIZE];
virtual ~Identifier() {}
+ const Identifier& operator=(const Identifier& rhs) {
+ m_HasValue = rhs.m_HasValue;
+ memcpy(m_Value, rhs.m_Value, SIZE);
+ return *this;
+ }
+
inline void Set(const byte_t* value) { m_HasValue = true; memcpy(m_Value, value, SIZE); }
inline const byte_t* Value() const { return m_Value; }
inline ui32_t Size() const { return SIZE; }
UUID(const byte_t* value) : Identifier<UUID_Length>(value) {}
UUID(const UUID& rhs) : Identifier<UUID_Length>(rhs) {}
virtual ~UUID() {}
-
- const UUID& operator=(const UUID& rhs) {
- if ( m_HasValue = rhs.m_HasValue )
- memcpy(m_Value, rhs.m_Value, UUID_Length);
- return *this;
- }
inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
return bin2UUIDhex(m_Value, Size(), buf, buf_len);
}
};
- void GenRandomUUID(byte_t* buf);
+ void GenRandomUUID(byte_t* buf); // buf must be UUID_Length or longer
void GenRandomValue(UUID&);
// a self-wiping key container
SymmetricKey(const byte_t* value) : Identifier<SymmetricKey_Length>(value) {}
SymmetricKey(const UUID& rhs) : Identifier<SymmetricKey_Length>(rhs) {}
virtual ~SymmetricKey() { memcpy(m_Value, NilKey, 16); m_HasValue = false; }
-
- const SymmetricKey& operator=(const SymmetricKey& rhs) {
- if ( m_HasValue = rhs.m_HasValue )
- memcpy(m_Value, rhs.m_Value, SymmetricKey_Length);
- return *this;
- }
};
void GenRandomValue(SymmetricKey&);
outbuf += "\"";
}
+ outbuf += ">";
+
// body contents and children
if ( ! m_ChildList.empty() )
{
- outbuf += ">\n";
+ outbuf += "\n";
// render body
if ( m_Body.length() > 0 )
(*i)->RenderElement(outbuf, depth + 1);
add_spacer(outbuf, depth);
- outbuf += "</";
- outbuf += m_Name;
- outbuf += ">\n";
}
else if ( m_Body.length() > 0 )
{
- outbuf += ">";
outbuf += m_Body;
- outbuf += "</";
- outbuf += m_Name;
- outbuf += ">\n";
- }
- else
- {
- outbuf += " />\n";
}
+
+ outbuf += "</";
+ outbuf += m_Name;
+ outbuf += ">\n";
}
InterchangeObject::Dump(stream);
fprintf(stream, " %22s = %s\n", "LastModifiedDate", LastModifiedDate.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %hu\n", "Version", Version);
- fprintf(stream, " %22s = %u\n", "ObjectModelVersion", ObjectModelVersion);
+ fprintf(stream, " %22s = %u\n", "ObjectModelVersion", ObjectModelVersion);
fprintf(stream, " %22s = %s\n", "PrimaryPackage", PrimaryPackage.EncodeHex(identbuf, IdentBufferLen));
fprintf(stream, " %22s:\n", "Identifications"); Identifications.Dump(stream);
fprintf(stream, " %22s = %s\n", "ContentStorage", ContentStorage.EncodeHex(identbuf, IdentBufferLen));
for ( int i = 1; i < argc; i++ )
{
- if ( (strcmp( argv[i], "-help") == 0) )
- {
- help_flag = true;
- continue;
- }
+ if ( (strcmp( argv[i], "-help") == 0) )
+ {
+ help_flag = true;
+ continue;
+ }
if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
{
if ( 1 ) // Options.verbose_flag )
{
- fprintf(stderr, "48Khz PCM Audio, %s fps (%lu spf)\n", "24",
+ fprintf(stderr, "48Khz PCM Audio, %s fps (%u spf)\n", "24",
PCM::CalcSamplesPerFrame(ADesc));
fputs("AudioDescriptor:\n", stderr);
PCM::AudioDescriptorDump(ADesc);
if ( ASDCP_SUCCESS(result) )
result = m_HeaderPart.InitFromFile(m_File);
- // if this is a three partition file, go to the body
- // partition and read off the partition pack
- if ( m_HeaderPart.m_RIP.PairArray.size() == 3 )
+ if ( ASDCP_SUCCESS(result) )
{
- Array<RIP::Pair>::iterator r_i = m_HeaderPart.m_RIP.PairArray.begin();
- r_i++;
- m_File.Seek((*r_i).ByteOffset);
+ // if this is a three partition file, go to the body
+ // partition and read the partition pack
+ if ( m_HeaderPart.m_RIP.PairArray.size() == 3 )
+ {
+ Array<RIP::Pair>::iterator r_i = m_HeaderPart.m_RIP.PairArray.begin();
+ r_i++;
+ m_File.Seek((*r_i).ByteOffset);
- result = m_BodyPart.InitFromFile(m_File);
+ result = m_BodyPart.InitFromFile(m_File);
+ }
+
+ m_EssenceStart = m_File.Tell();
}
- m_EssenceStart = m_File.Tell();
- return RESULT_OK;
+ return result;
}
using namespace ASDCP;
using Kumu::DefaultLogSink;
-const char* PACKAGE = "klvwalk";
-
//------------------------------------------------------------------------------------------
//
+// command line option parser class
+static const char* PACKAGE = "klvwalk"; // program name for messages
+typedef std::list<std::string> FileList_t;
-int
-main(int argc, char** argv)
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \
+ { \
+ fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+ return; \
+ }
+
+//
+void
+banner(FILE* stream = stdout)
{
- Result_t result = RESULT_OK;
- bool read_mxf = false;
- int arg_i = 1;
+ fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2005-2006 John Hurst\n\
+%s is part of the asdcplib DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+ PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
- if ( argc > arg_i && strcmp(argv[1], "-r") == 0 )
- {
- read_mxf = true;
- arg_i++;
- }
+//
+void
+usage(FILE* stream = stdout)
+{
+ fprintf(stream, "\
+USAGE: %s [-r] [-v] <input-file> [<input-file2> ...]\n\
+\n\
+ %s [-h|-help] [-V]\n\
+\n\
+ -h | -help - Show help\n\
+ -r - When KLV data is an OPAtom file, additionally\n\
+ display OPAtom headers\n\
+ -v - Verbose. Prints informative messages to stderr\n\
+ -V - Show version information\n\
+\n\
+ NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+ o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
- if ( argc - arg_i != 1 )
- {
- fprintf(stderr, "usage: %s [-r] <infile>\n", PACKAGE);
- return 1;
- }
+//
+//
+ class CommandOptions
+ {
+ CommandOptions();
- fprintf(stderr, "Opening file %s\n", argv[arg_i]);
+ public:
+ bool error_flag; // true if the given options are in error or not complete
+ bool version_flag; // true if the version display option was selected
+ bool help_flag; // true if the help display option was selected
+ bool verbose_flag; // true if the informative messages option was selected
+ bool read_mxf_flag; // true if the -r option was selected
+ FileList_t inFileList; // File to operate on
- if ( read_mxf )
- {
- Kumu::FileReader Reader;
- ASDCP::MXF::OPAtomHeader Header;
+ CommandOptions(int argc, const char** argv) :
+ error_flag(true), version_flag(false), help_flag(false), verbose_flag(false), read_mxf_flag(false)
+ {
+ for ( int i = 1; i < argc; i++ )
+ {
- result = Reader.OpenRead(argv[arg_i]);
+ if ( (strcmp( argv[i], "-help") == 0) )
+ {
+ help_flag = true;
+ continue;
+ }
+
+ if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+ {
+ switch ( argv[i][1] )
+ {
- if ( ASDCP_SUCCESS(result) )
- result = Header.InitFromFile(Reader);
+ case 'h': help_flag = true; break;
+ case 'r': read_mxf_flag = true; break;
+ case 'V': version_flag = true; break;
+ case 'v': verbose_flag = true; break;
- Header.Dump(stdout);
+ default:
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+ else
+ {
+ if ( argv[i][0] != '-' )
+ inFileList.push_back(argv[i]);
- if ( ASDCP_SUCCESS(result) )
- {
- ASDCP::MXF::OPAtomIndexFooter Index;
- result = Reader.Seek(Header.FooterPartition);
+ else
+ {
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+ }
- if ( ASDCP_SUCCESS(result) )
- {
- Index.m_Lookup = &Header.m_Primer;
- result = Index.InitFromFile(Reader);
- }
+ if ( help_flag || version_flag )
+ return;
+
+ if ( inFileList.empty() )
+ {
+ fputs("Input filename(s) required.\n", stderr);
+ return;
+ }
+
+ error_flag = false;
+ }
+ };
- if ( ASDCP_SUCCESS(result) )
- Index.Dump(stdout);
- }
- }
- else // dump klv
- {
- Kumu::FileReader Reader;
- KLVFilePacket KP;
- result = Reader.OpenRead(argv[arg_i]);
+//---------------------------------------------------------------------------------------------------
+//
+
+int
+main(int argc, const char** argv)
+{
+ CommandOptions Options(argc, argv);
- if ( ASDCP_SUCCESS(result) )
- result = KP.InitFromFile(Reader);
+ if ( Options.version_flag )
+ banner();
- while ( ASDCP_SUCCESS(result) )
+ if ( Options.help_flag )
+ usage();
+
+ if ( Options.version_flag || Options.help_flag )
+ return 0;
+
+ if ( Options.error_flag )
+ {
+ fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+ return 3;
+ }
+
+ FileList_t::iterator fi;
+ Result_t result = RESULT_OK;
+
+ for ( fi = Options.inFileList.begin(); ASDCP_SUCCESS(result) && fi != Options.inFileList.end(); fi++ )
+ {
+ if (Options.verbose_flag)
+ fprintf(stderr, "Opening file %s\n", ((*fi).c_str()));
+
+ if ( Options.read_mxf_flag )
{
- KP.Dump(stdout, true);
- result = KP.InitFromFile(Reader);
+ Kumu::FileReader Reader;
+ ASDCP::MXF::OPAtomHeader Header;
+
+ result = Reader.OpenRead((*fi).c_str());
+
+ if ( ASDCP_SUCCESS(result) )
+ result = Header.InitFromFile(Reader);
+
+ Header.Dump(stdout);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ASDCP::MXF::OPAtomIndexFooter Index;
+ result = Reader.Seek(Header.FooterPartition);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ Index.m_Lookup = &Header.m_Primer;
+ result = Index.InitFromFile(Reader);
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ Index.Dump(stdout);
+ }
+ }
+ else // dump klv
+ {
+ Kumu::FileReader Reader;
+ KLVFilePacket KP;
+
+ result = Reader.OpenRead((*fi).c_str());
+
+ if ( ASDCP_SUCCESS(result) )
+ result = KP.InitFromFile(Reader);
+
+ while ( ASDCP_SUCCESS(result) )
+ {
+ KP.Dump(stdout, true);
+ result = KP.InitFromFile(Reader);
+ }
+
+ if( result == RESULT_ENDOFFILE )
+ result = RESULT_OK;
}
-
- if( result == RESULT_ENDOFFILE )
- result = RESULT_OK;
}
if ( ASDCP_FAILURE(result) )
{
fputs("Program stopped on error.\n", stderr);
-
+
if ( result != RESULT_FAIL )
{
fputs(result, stderr);
fputc('\n', stderr);
}
-
+
return 1;
}
-
+
return 0;
}
--- /dev/null
+/*
+Copyright (c) 2005-2006, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*! \file kmfilegen.cpp
+ \version $Id$
+ \brief large file test program
+*/
+
+
+#include "AS_DCP.h"
+#include <iostream>
+#include <KM_fileio.h>
+#include <KM_prng.h>
+#include <openssl/aes.h>
+#include <assert.h>
+
+using namespace Kumu;
+
+// constants
+static const char* PACKAGE = "kmfilegen"; // program name for messages
+const ui32_t RNG_KEY_SIZE = 16;
+const ui32_t RNG_KEY_SIZE_BITS = 128;
+const ui32_t RNG_BLOCK_SIZE = 16;
+
+// globals
+ui32_t s_Nonce = 0;
+FortunaRNG s_RNG;
+
+
+//------------------------------------------------------------------------------------------
+//
+// command line option parser class
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \
+ { \
+ fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+ return; \
+ }
+
+//
+void
+banner(FILE* stream = stdout)
+{
+ fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2005-2006 John Hurst\n\
+%s is part of the asdcplib DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+ PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
+
+
+//
+void
+usage(FILE* stream = stdout)
+{
+ fprintf(stream, "\
+USAGE: %s [-c <file-size>][-o <fwd|rev|rand>][-w <filename>][-v]\n\
+ <filename>\n\
+\n\
+ %s [-h|-help] [-V]\n\
+\n\
+ -c <file-size> - Create a test file containing <file-size> megabytes of data\n\
+ -h | -help - Show help\n\
+ -o <order> - Specify order used when validating a file.\n\
+ One of fwd|rev|rand, default is rand\n\
+ -v - Verbose. Prints informative messages to stderr\n\
+ -V - Show version information\n\
+ -w - Read-Validate-Write - file is written to <filename>\n\
+ (sequential read only)\n\
+\n\
+ NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+ o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
+
+enum MajorMode_t {
+ MMT_NONE,
+ MMT_CREATE,
+ MMT_VALIDATE,
+ MMT_VAL_WRITE
+};
+
+//
+class CommandOptions
+{
+ CommandOptions();
+
+public:
+ bool error_flag; // true if the given options are in error or not complete
+ const char* order; // one of fwd|rev|rand
+ bool verbose_flag; // true if the verbose option was selected
+ bool version_flag; // true if the version display option was selected
+ bool help_flag; // true if the help display option was selected
+ const char* filename; // filename to be processed
+ const char* write_filename; // filename to write with val_write_flag
+ ui32_t chunk_count;
+ MajorMode_t mode; // MajorMode selector
+
+ //
+ CommandOptions(int argc, const char** argv) :
+ error_flag(true), order(0), verbose_flag(false), version_flag(false), help_flag(false),
+ filename(""), write_filename(""), chunk_count(0), mode(MMT_VALIDATE)
+ {
+ order = "rand";
+
+ for ( int i = 1; i < argc; i++ )
+ {
+
+ if ( (strcmp( argv[i], "-help") == 0) )
+ {
+ help_flag = true;
+ continue;
+ }
+
+ if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+ {
+ switch ( argv[i][1] )
+ {
+ case 'c':
+ mode = MMT_CREATE;
+ TEST_EXTRA_ARG(i, 'c');
+ chunk_count = atoi(argv[i]);
+ break;
+
+ case 'V': version_flag = true; break;
+ case 'h': help_flag = true; break;
+ case 'v': verbose_flag = true; break;
+
+ case 'o':
+ TEST_EXTRA_ARG(i, 'o');
+ order = argv[i];
+
+ if ( strcmp(order, "fwd" ) != 0
+ && strcmp(order, "rev" ) != 0
+ && strcmp(order, "rand" ) != 0 )
+ {
+ fprintf(stderr, "Unexpected order token: %s, expecting fwd|rev|rand\n", order);
+ return;
+ }
+
+ break;
+
+ case 'w':
+ mode = MMT_VAL_WRITE;
+ TEST_EXTRA_ARG(i, 'w');
+ write_filename = argv[i];
+ break;
+
+ default:
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+ else
+ {
+ if (argv[i][0] != '-' )
+ {
+ if ( filename != "" )
+ {
+ fprintf(stderr, "Extra filename found: %s\n", argv[i]);
+ return;
+ }
+ else
+ filename = argv[i];
+ }
+ else
+ {
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+ }
+
+ if ( help_flag || version_flag )
+ return;
+
+ if ( strlen ( filename ) == 0 )
+ {
+ fprintf(stderr, "Filename required.\n");
+ return;
+ }
+
+ if ( strcmp ( filename, write_filename ) == 0 )
+ {
+ fprintf(stderr, "Output and input files must be different.\n");
+ return;
+ }
+
+ error_flag = false;
+ }
+};
+
+//------------------------------------------------------------------------------------------
+
+
+//
+#pragma pack(4)
+class CTR_Setup
+{
+ AES_KEY m_Context;
+ byte_t m_key[RNG_KEY_SIZE];
+ byte_t m_preamble[8];
+ ui32_t m_nonce;
+ ui32_t m_ctr;
+
+ KM_NO_COPY_CONSTRUCT(CTR_Setup);
+
+public:
+ CTR_Setup() {}
+ ~CTR_Setup() {}
+
+ inline ui32_t Nonce() { return KM_i32_LE(m_nonce); }
+ inline ui32_t WriteSize() { return ( sizeof(m_key) + sizeof(m_preamble)
+ + sizeof(m_nonce) + sizeof(m_ctr) ); }
+
+ //
+ void SetupWrite(byte_t* buf)
+ {
+ assert(buf);
+ s_RNG.FillRandom(m_key, WriteSize());
+ assert(s_Nonce > 0);
+ m_nonce = KM_i32_LE(s_Nonce--);
+ m_ctr &= KM_i32_LE(0x7fffffff); // make sure we have 2GB headroom
+ memcpy(buf, m_key, WriteSize());
+ AES_set_encrypt_key(m_key, RNG_KEY_SIZE_BITS, &m_Context);
+ }
+
+ //
+ void SetupRead(const byte_t* buf)
+ {
+ assert(buf);
+ memcpy(m_key, buf, WriteSize());
+ AES_set_encrypt_key(m_key, RNG_KEY_SIZE_BITS, &m_Context);
+ }
+
+ //
+ void FillRandom(byte_t* buf, ui32_t buf_len)
+ {
+ ui32_t gen_count = 0;
+ while ( gen_count + RNG_BLOCK_SIZE <= buf_len )
+ {
+ AES_encrypt(m_preamble, buf + gen_count, &m_Context);
+ m_ctr = KM_i32_LE(KM_i32_LE(m_ctr) + 1);
+ gen_count += RNG_BLOCK_SIZE;
+ }
+ }
+};
+
+//
+Result_t
+CreateLargeFile(CommandOptions& Options)
+{
+ ui32_t write_total = 0;
+ ui32_t write_count = 0;
+ FileWriter Writer;
+ ByteString FB;
+
+ FB.Capacity(Megabyte);
+ assert(FB.Capacity() == Megabyte);
+
+ fprintf(stderr, "Writing %lu chunks:\n", Options.chunk_count);
+ s_Nonce = Options.chunk_count;
+ Result_t result = Writer.OpenWrite(Options.filename);
+
+ while ( KM_SUCCESS(result) && write_total < Options.chunk_count )
+ {
+ if ( KM_SUCCESS(result))
+ {
+ CTR_Setup CTR;
+ CTR.SetupWrite(FB.Data());
+ CTR.FillRandom(FB.Data() + CTR.WriteSize(), Megabyte - CTR.WriteSize());
+ result = Writer.Write(FB.RoData(), Megabyte, &write_count);
+ assert(write_count == Megabyte);
+ fprintf(stderr, "\r%8lu ", ++write_total);
+ }
+ }
+
+ fputs("\n", stderr);
+
+ return result;
+}
+
+//
+Result_t
+validate_chunk(ByteString& FB, ByteString& CB, ui32_t* nonce_value)
+{
+ assert(nonce_value);
+ CTR_Setup CTR;
+ CTR.SetupRead(FB.RoData());
+
+ CTR.FillRandom(CB.Data() + CTR.WriteSize(),
+ Megabyte - CTR.WriteSize());
+
+ if ( memcmp(FB.RoData() + CTR.WriteSize(),
+ CB.RoData() + CTR.WriteSize(),
+ Megabyte - CTR.WriteSize()) != 0 )
+ {
+ fprintf(stderr, "Check data mismatched in chunk\n");
+ return RESULT_FAIL;
+ }
+
+ *nonce_value = CTR.Nonce();
+
+ return RESULT_OK;
+}
+
+//
+struct read_list_t
+{
+ ui32_t nonce;
+ Kumu::fpos_t position;
+};
+
+//
+void
+randomize_list(read_list_t* read_list, ui32_t check_total)
+{
+ static ui32_t tmp_ints[4];
+ static ui32_t seq = 0;
+
+ for ( ui32_t j = 0; j < check_total; j++ )
+ {
+ if ( seq > 3 )
+ seq = 0;
+
+ if ( seq == 0 )
+ s_RNG.FillRandom((byte_t*)tmp_ints, 16);
+
+ ui32_t i = tmp_ints[seq++] % (check_total - 1);
+
+ if ( i == j )
+ continue;
+
+ read_list_t t = read_list[i];
+ read_list[i] = read_list[j];
+ read_list[j] = t;
+ }
+}
+
+//
+Result_t
+ReadValidateWriteLargeFile(CommandOptions& Options)
+{
+ assert(Options.write_filename);
+ ui32_t check_total = 0;
+ ui32_t write_total = 0;
+ ui32_t read_count = 0;
+ ui32_t write_count = 0;
+ FileReader Reader;
+ FileWriter Writer;
+ ByteString FB, CB; // Frame Buffer and Check Buffer
+
+
+ FB.Capacity(Megabyte);
+ assert(FB.Capacity() == Megabyte);
+ CB.Capacity(Megabyte);
+ assert(CB.Capacity() == Megabyte);
+
+ Result_t result = Reader.OpenRead(Options.filename);
+
+ if ( KM_SUCCESS(result) )
+ result = Writer.OpenWrite(Options.write_filename);
+
+ // read the first chunk and get set up
+ while ( KM_SUCCESS(result) )
+ {
+ result = Reader.Read(FB.Data(), Megabyte, &read_count);
+
+ if ( KM_SUCCESS(result) )
+ {
+ if ( read_count < Megabyte )
+ {
+ fprintf(stderr, "Read() returned short buffer: %lu\n", read_count);
+ result = RESULT_FAIL;
+ }
+
+ result = validate_chunk(FB, CB, &check_total);
+
+ if ( KM_SUCCESS(result) )
+ {
+ result = Writer.Write(FB.RoData(), Megabyte, &write_count);
+ assert(write_count == Megabyte);
+ fprintf(stderr, "\r%8lu ", ++write_total);
+ }
+ }
+ else if ( result == RESULT_ENDOFFILE )
+ {
+ result = RESULT_OK;
+ break;
+ }
+ }
+
+ fputs("\n", stderr);
+ return result;
+}
+
+
+//
+Result_t
+ValidateLargeFile(CommandOptions& Options)
+{
+ ui32_t check_total = 0;
+ ui32_t read_count = 0;
+ ui32_t read_list_i = 0;
+ read_list_t* read_list = 0;
+ FileReader Reader;
+ ByteString FB, CB; // Frame Buffer and Check Buffer
+
+ FB.Capacity(Megabyte);
+ assert(FB.Capacity() == Megabyte);
+ CB.Capacity(Megabyte);
+ assert(CB.Capacity() == Megabyte);
+
+ Result_t result = Reader.OpenRead(Options.filename);
+
+ // read the first chunk and get set up
+ if ( KM_SUCCESS(result) )
+ {
+ result = Reader.Read(FB.Data(), Megabyte, &read_count);
+
+ if ( read_count < Megabyte )
+ {
+ fprintf(stderr, "Read() returned short buffer: %lu\n", read_count);
+ result = RESULT_FAIL;
+ }
+ else if ( KM_SUCCESS(result) )
+ result = validate_chunk(FB, CB, &check_total);
+
+ if ( KM_SUCCESS(result) )
+ {
+ fprintf(stderr, "Validating %lu chunk%s in %s order:\n",
+ check_total, (check_total == 1 ? "" : "s"), Options.order);
+ assert(read_list == 0);
+ read_list = (read_list_t*)malloc(check_total * sizeof(read_list_t));
+ assert(read_list);
+
+ // Set up an index to the chunks. The chunks are written
+ // to the file in order of descending nonce value.
+ if ( strcmp(Options.order, "fwd") == 0 )
+ {
+ for ( ui32_t i = 0; i < check_total; i++ )
+ {
+ read_list[i].nonce = check_total - i;
+ Kumu::fpos_t ofst = check_total - read_list[i].nonce;
+ read_list[i].position = ofst * (Kumu::fpos_t)Megabyte;
+ }
+ }
+ else
+ {
+ for ( ui32_t i = 0; i < check_total; i++ )
+ {
+ read_list[i].nonce = i + 1;
+ Kumu::fpos_t ofst = check_total - read_list[i].nonce;
+ read_list[i].position = ofst * (Kumu::fpos_t)Megabyte;
+ }
+
+ if ( strcmp(Options.order, "rand") == 0 )
+ randomize_list(read_list, check_total); // this makes it random
+ }
+ }
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ assert(read_list);
+ ui32_t nonce = 0;
+
+ for ( read_list_i = 0;
+ read_list_i < check_total && KM_SUCCESS(result);
+ read_list_i++ )
+ {
+ fprintf(stderr, "\r%8lu [%8lu] ", read_list_i+1, read_list[read_list_i]);
+ result = Reader.Seek(read_list[read_list_i].position);
+
+ if ( KM_SUCCESS(result) )
+ result = Reader.Read(FB.Data(), Megabyte, &read_count);
+
+ if ( result == RESULT_ENDOFFILE )
+ break;
+
+ else if ( read_count < Megabyte )
+ {
+ fprintf(stderr, "Read() returned short buffer: %lu\n", read_count);
+ result = RESULT_FAIL;
+ }
+ else if ( KM_SUCCESS(result) )
+ {
+ result = validate_chunk(FB, CB, &nonce);
+
+ if ( nonce != read_list[read_list_i].nonce )
+ {
+ fprintf(stderr, "Nonce mismatch: expecting %lu, got %lu\n",
+ nonce, read_list[read_list_i].nonce);
+
+ return RESULT_FAIL;
+ }
+ }
+ }
+ }
+
+ fputs("\n", stderr);
+
+ if ( result == RESULT_ENDOFFILE )
+ {
+ if ( check_total == read_list_i )
+ result = RESULT_OK;
+ else
+ {
+ fprintf(stderr, "Unexpected chunk count, got %lu, wanted %lu\n",
+ read_list_i, check_total);
+ result = RESULT_FAIL;
+ }
+ }
+
+ return result;
+}
+
+//
+int
+main(int argc, const char **argv)
+{
+ Result_t result = RESULT_FAIL;
+ CommandOptions Options(argc, argv);
+
+ if ( Options.version_flag )
+ banner();
+
+ if ( Options.help_flag )
+ usage();
+
+ if ( Options.version_flag || Options.help_flag )
+ return 0;
+
+ if ( Options.error_flag )
+ {
+ fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+ return 3;
+ }
+
+ switch ( Options.mode )
+ {
+
+ case MMT_CREATE:
+ result = CreateLargeFile(Options);
+ break;
+
+ case MMT_VALIDATE:
+ result = ValidateLargeFile(Options);
+ break;
+
+ case MMT_VAL_WRITE:
+ result = ReadValidateWriteLargeFile(Options);
+ break;
+ }
+
+ if ( result != RESULT_OK )
+ {
+ fputs("Program stopped on error.\n", stderr);
+
+ if ( result != RESULT_FAIL )
+ {
+ fputs(result.Label(), stderr);
+ fputc('\n', stderr);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+//
+// end kmfilegen.cpp
+//
--- /dev/null
+/*
+Copyright (c) 2005-2006, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file kmrandgen.cpp
+ \version $Id$
+ \brief psuedo-random number generation utility
+ */
+
+#include "AS_DCP.h"
+#include <KM_fileio.h>
+#include <KM_prng.h>
+#include <ctype.h>
+
+using namespace Kumu;
+
+const ui32_t RandBlockSize = 16;
+const char* PACKAGE = "kmrandgen";
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \
+ { \
+ fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+ return; \
+ }
+
+//
+void
+banner(FILE* stream = stdout)
+{
+ fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2003-2006 John Hurst\n\n\
+%s is part of the asdcp DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+ PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
+
+//
+void
+usage(FILE* stream = stdout)
+{
+ fprintf(stream, "\
+USAGE: %s [-b|-c] [-n] [-s <size>]\n\
+\n\
+ %s [-h|-help] [-V]\n\
+\n\
+ -b - Output a stream of binary data\n\
+ -c - Output a C-language struct containing the values\n\
+ -h | -help - Show help\n\
+ -n - Suppress newlines\n\
+ -s <size> - Number of random bytes to generate (default 32, supplied value\n\
+ is rounded up to nearest multiple of 16)\n\
+ -v - Verbose. Prints informative messages to stderr\n\
+ -V - Show version information\n\
+\n\
+ NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+ o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
+
+//
+class CommandOptions
+{
+ CommandOptions();
+
+public:
+ bool error_flag; // true if the given options are in error or not complete
+ bool no_newline_flag; //
+ bool c_array_flag; //
+ bool binary_flag; //
+ bool verbose_flag; // true if the verbose option was selected
+ bool version_flag; // true if the version display option was selected
+ bool help_flag; // true if the help display option was selected
+ ui32_t request_size;
+
+ //
+ CommandOptions(int argc, const char** argv) :
+ error_flag(true), no_newline_flag(false), c_array_flag(false), binary_flag(false),
+ verbose_flag(false), version_flag(false), help_flag(false), request_size(32)
+ {
+ ui32_t tmp_size = 0, diff = 0;
+
+ for ( int i = 1; i < argc; i++ )
+ {
+
+ if ( (strcmp( argv[i], "-help") == 0) )
+ {
+ help_flag = true;
+ continue;
+ }
+
+ if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+ {
+ switch ( argv[i][1] )
+ {
+ case 'b': binary_flag = true; break;
+ case 'c': c_array_flag = true; break;
+ case 'n': no_newline_flag = true; break;
+ case 'h': help_flag = true; break;
+
+ case 's':
+ TEST_EXTRA_ARG(i, 's');
+ tmp_size = atoi(argv[i]);
+ diff = tmp_size % RandBlockSize;
+
+ if ( diff != 0 )
+ tmp_size += RandBlockSize - diff;
+
+ request_size = tmp_size;
+ break;
+
+ case 'v': verbose_flag = true; break;
+ case 'V': version_flag = true; break;
+
+ default:
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+
+ if ( help_flag || version_flag )
+ return;
+
+ if ( binary_flag && c_array_flag )
+ {
+ fprintf(stderr, "Error, must use only one of -b and -c options.\n");
+ return;
+ }
+
+ error_flag = false;
+ }
+};
+
+
+//
+int
+main(int argc, const char** argv)
+{
+ CommandOptions Options(argc, argv);
+
+ if ( Options.version_flag )
+ banner();
+
+ if ( Options.help_flag )
+ usage();
+
+ if ( Options.version_flag || Options.help_flag )
+ return 0;
+
+ if ( Options.error_flag )
+ {
+ fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+ return 3;
+ }
+
+ FortunaRNG RandGen;
+ ByteString Buf(Kumu::Kilobyte);
+
+ if ( Options.verbose_flag )
+ fprintf(stderr, "Creating %d random values.\n", Options.request_size);
+
+ if ( Options.binary_flag )
+ {
+ for ( ui32_t i = 0; i < Options.request_size; i += Kumu::Kilobyte )
+ {
+ RandGen.FillRandom(Buf);
+ ui32_t write_size = ((i + Kumu::Kilobyte) > Options.request_size) ? Options.request_size - i : Kumu::Kilobyte;
+ fwrite((byte_t*)Buf.Data(), 1, write_size, stdout);
+ }
+ }
+ else if ( Options.c_array_flag )
+ {
+ byte_t* p = Buf.Data();
+ printf("byte_t rand_buf[%u] = {\n", Options.request_size);
+
+ while ( Options.request_size > 0 )
+ {
+ RandGen.FillRandom(p, RandBlockSize);
+ fputc(' ', stdout);
+
+ for ( ui32_t i = 0; i < RandBlockSize; i++ )
+ printf(" 0x%02x,", p[i]);
+
+ fputc('\n', stdout);
+ Options.request_size -= RandBlockSize;
+ }
+
+ fputs("};", stdout);
+
+ if ( ! Options.no_newline_flag )
+ fputc('\n', stdout);
+ }
+ else
+ {
+ char hex_buf[64];
+ byte_t* p = Buf.Data();
+
+ for ( ui32_t i = 0; i < Options.request_size; i += RandBlockSize )
+ {
+ RandGen.FillRandom(p, RandBlockSize);
+ bin2hex(p, RandBlockSize, hex_buf, 64);
+ fputs(hex_buf, stdout);
+
+ if ( ! Options.no_newline_flag )
+ fputc('\n', stdout);
+ }
+ }
+
+ return 0;
+}
+
+
+//
+// end kmrandgen.cpp
+//
--- /dev/null
+/*
+Copyright (c) 2005-2006, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file kmuuidgen.cpp
+ \version $Id$
+ \brief UUID generation utility
+ */
+
+#include "AS_DCP.h"
+#include <KM_util.h>
+#include <ctype.h>
+
+
+const char* PACKAGE = "kmuuidgen";
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \
+ { \
+ fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+ return; \
+ }
+
+//
+void
+banner(FILE* stream = stdout)
+{
+ fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2003-2006 John Hurst\n\n\
+%s is part of the asdcp DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+ PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
+
+//
+void
+usage(FILE* stream = stdout)
+{
+ fprintf(stream, "\
+USAGE: %s [-c][-n]\n\
+\n\
+ %s [-h|-help] [-V]\n\
+\n\
+ -c - Output a C-language struct containing the value\n\
+ -h | -help - Show help\n\
+ -n - Suppress the newline\n\
+ -v - Verbose. Prints informative messages to stderr\n\
+ -V - Show version information\n\
+\n\
+ NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+ o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
+
+//
+class CommandOptions
+{
+ CommandOptions();
+
+public:
+ bool error_flag; // true if the given options are in error or not complete
+ bool no_newline_flag; //
+ bool c_array_flag; //
+ bool version_flag; // true if the version display option was selected
+ bool help_flag; // true if the help display option was selected
+ bool verbose_flag; // true if the verbose flag was selected
+
+ //
+ CommandOptions(int argc, const char** argv) :
+ error_flag(true), no_newline_flag(false), c_array_flag(false), version_flag(false),
+ help_flag(false), verbose_flag(false)
+ {
+ for ( int i = 1; i < argc; i++ )
+ {
+
+ if ( (strcmp( argv[i], "-help") == 0) )
+ {
+ help_flag = true;
+ continue;
+ }
+
+ if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+ {
+ switch ( argv[i][1] )
+ {
+ case 'c': c_array_flag = true; break;
+ case 'n': no_newline_flag = true; break;
+ case 'h': help_flag = true; break;
+ case 'v': verbose_flag = true; break;
+ case 'V': version_flag = true; break;
+
+ default:
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ return;
+ }
+ }
+
+ if ( help_flag || version_flag )
+ return;
+
+ error_flag = false;
+ }
+};
+
+
+
+//
+int
+main(int argc, const char** argv)
+{
+ CommandOptions Options(argc, argv);
+
+ if ( Options.version_flag )
+ banner();
+
+ if ( Options.help_flag )
+ usage();
+
+ if ( Options.version_flag || Options.help_flag )
+ return 0;
+
+ if ( Options.error_flag )
+ {
+ fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+ return 3;
+ }
+
+ Kumu::UUID UUID;
+ Kumu::GenRandomValue(UUID);
+ char uuid_buf[40];
+
+ if ( Options.c_array_flag )
+ {
+ const byte_t* p = UUID.Value();
+
+ printf("\
+byte_t uuid_buf[] = {\n\
+ // %s\n ",
+ UUID.EncodeHex(uuid_buf, 40));
+
+ for ( ui32_t i = 0; i < 16; i++ )
+ printf(" 0x%02x,", p[i]);
+
+ printf("\n");
+ printf("};\n");
+ return 0;
+ }
+ else
+ {
+ fputs(UUID.EncodeHex(uuid_buf, 40), stdout);
+ }
+
+ if ( Options.no_newline_flag == 0 )
+ printf("\n");
+
+ return 0;
+}
+
+
+//
+// end kmuuidgen.cpp
+//