diff options
| author | tmccolm <tmccolm@cinecert.com> | 2006-06-23 19:48:03 +0000 |
|---|---|---|
| committer | tmccolm <> | 2006-06-23 19:48:03 +0000 |
| commit | c589ee9d47d9f00aa4be32c5832a44ce466f014d (patch) | |
| tree | d285585caea07384dc75c5cb2a697df821437f72 /src | |
| parent | 5e91ca52284adc91a42d6fe389c9cc70a33126a6 (diff) | |
2006/06/23 tmccolm
Diffstat (limited to 'src')
| -rwxr-xr-x | src/AS_DCP_MXF.cpp | 2 | ||||
| -rwxr-xr-x | src/JP2K.cpp | 18 | ||||
| -rwxr-xr-x | src/KLV.h | 12 | ||||
| -rwxr-xr-x | src/KM_util.cpp | 90 | ||||
| -rwxr-xr-x | src/KM_util.h | 22 | ||||
| -rw-r--r-- | src/KM_xml.cpp | 19 | ||||
| -rwxr-xr-x | src/MXF.cpp | 2 | ||||
| -rwxr-xr-x | src/asdcp-test.cpp | 10 | ||||
| -rw-r--r-- | src/blackwave.cpp | 2 | ||||
| -rwxr-xr-x | src/h__Reader.cpp | 22 | ||||
| -rwxr-xr-x | src/klvwalk.cpp | 233 | ||||
| -rwxr-xr-x | src/kmfilegen.cpp | 604 | ||||
| -rw-r--r-- | src/kmrandgen.cpp | 248 | ||||
| -rw-r--r-- | src/kmuuidgen.cpp | 195 |
14 files changed, 1330 insertions, 149 deletions
diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp index 1c8b6e9..5c8fc16 100755 --- a/src/AS_DCP_MXF.cpp +++ b/src/AS_DCP_MXF.cpp @@ -447,7 +447,7 @@ ASDCP::IntegrityPack::TestValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID, // 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; } diff --git a/src/JP2K.cpp b/src/JP2K.cpp index 3c798ce..14789f1 100755 --- a/src/JP2K.cpp +++ b/src/JP2K.cpp @@ -120,15 +120,15 @@ ASDCP::JP2K::Accessor::SIZ::Dump(FILE* stream) 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 ) { @@ -102,12 +102,6 @@ inline const char* ui64sz(ui64_t i, char* buf) 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; }; @@ -120,12 +114,6 @@ inline const char* ui64sz(ui64_t i, char* buf) 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; diff --git a/src/KM_util.cpp b/src/KM_util.cpp index a07d33e..7dd6719 100755 --- a/src/KM_util.cpp +++ b/src/KM_util.cpp @@ -433,12 +433,12 @@ Kumu::GenRandomUUID(byte_t* buf) // 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); } @@ -796,41 +796,73 @@ Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const 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; } diff --git a/src/KM_util.h b/src/KM_util.h index 344cfd1..9d975b9 100755 --- a/src/KM_util.h +++ b/src/KM_util.h @@ -167,8 +167,6 @@ namespace Kumu template <ui32_t SIZE> class Identifier : public IArchive { - const Identifier& operator=(const Identifier& rhs); - protected: bool m_HasValue; byte_t m_Value[SIZE]; @@ -183,6 +181,12 @@ namespace Kumu 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; } @@ -262,19 +266,13 @@ namespace Kumu 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 @@ -292,12 +290,6 @@ namespace Kumu 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&); diff --git a/src/KM_xml.cpp b/src/KM_xml.cpp index 794e2e7..605ea11 100644 --- a/src/KM_xml.cpp +++ b/src/KM_xml.cpp @@ -138,10 +138,12 @@ Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth) outbuf += "\""; } + outbuf += ">"; + // body contents and children if ( ! m_ChildList.empty() ) { - outbuf += ">\n"; + outbuf += "\n"; // render body if ( m_Body.length() > 0 ) @@ -151,22 +153,15 @@ Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth) (*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"; } diff --git a/src/MXF.cpp b/src/MXF.cpp index 9d4fba8..0913f1b 100755 --- a/src/MXF.cpp +++ b/src/MXF.cpp @@ -577,7 +577,7 @@ ASDCP::MXF::Preface::Dump(FILE* stream) 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)); diff --git a/src/asdcp-test.cpp b/src/asdcp-test.cpp index 5eaffe3..e43569e 100755 --- a/src/asdcp-test.cpp +++ b/src/asdcp-test.cpp @@ -277,11 +277,11 @@ public: 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 ) { diff --git a/src/blackwave.cpp b/src/blackwave.cpp index c84774f..b704b47 100644 --- a/src/blackwave.cpp +++ b/src/blackwave.cpp @@ -169,7 +169,7 @@ make_black_wav_file(CommandOptions& Options) 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); diff --git a/src/h__Reader.cpp b/src/h__Reader.cpp index 1ebc5d4..2179ca6 100755 --- a/src/h__Reader.cpp +++ b/src/h__Reader.cpp @@ -108,19 +108,23 @@ ASDCP::h__Reader::OpenMXFRead(const char* filename) 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; } diff --git a/src/klvwalk.cpp b/src/klvwalk.cpp index 395aa54..467eff9 100755 --- a/src/klvwalk.cpp +++ b/src/klvwalk.cpp @@ -42,94 +42,217 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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; } diff --git a/src/kmfilegen.cpp b/src/kmfilegen.cpp new file mode 100755 index 0000000..bc1243d --- /dev/null +++ b/src/kmfilegen.cpp @@ -0,0 +1,604 @@ +/* +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 +// diff --git a/src/kmrandgen.cpp b/src/kmrandgen.cpp new file mode 100644 index 0000000..c953244 --- /dev/null +++ b/src/kmrandgen.cpp @@ -0,0 +1,248 @@ +/* +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 +// diff --git a/src/kmuuidgen.cpp b/src/kmuuidgen.cpp new file mode 100644 index 0000000..bb9afaf --- /dev/null +++ b/src/kmuuidgen.cpp @@ -0,0 +1,195 @@ +/* +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 +// |
