par2cmdline.h

Go to the documentation of this file.
00001 // This file is part of par2cmdline (a PAR 2.0 compatible file verification and
00002 // repair tool). See https://parchive.sourceforge.net for details of PAR 2.0.
00003 //
00004 // Copyright (c) 2003 Peter Brian Clements
00005 //
00006 // par2cmdline is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 //
00011 // par2cmdline is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014 // GNU General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU General Public License
00017 // along with this program; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00019 //
00020 // Modifications for concurrent processing, Unicode support, and hierarchial
00021 // directory support are Copyright (c) 2007-2008 Vincent Tan.
00022 // Search for "#if WANT_CONCURRENT" for concurrent code.
00023 // Concurrent processing utilises Intel Thread Building Blocks 2.0,
00024 // Copyright (c) 2007 Intel Corp.
00025 
00026 #ifndef __PARCMDLINE_H__
00027 #define __PARCMDLINE_H__
00028 
00029 
00030 #ifdef WIN32
00031 // Windows includes
00032 #define WIN32_LEAN_AND_MEAN
00033 #include 
00034 
00035 // System includes
00036 #include 
00037 #include 
00038 #include 
00039 #include 
00040 #include 
00041 #include 
00042 #include 
00043 #include 
00044 #include 
00045 
00046 #define snprintf _snprintf
00047 
00048 #define __LITTLE_ENDIAN 1234
00049 #define __BIG_ENDIAN 4321
00050 #define __PDP_ENDIAN 3412
00051 
00052 #define __BYTE_ORDER __LITTLE_ENDIAN
00053 
00054 typedef unsigned char    u8;
00055 typedef unsigned short   u16;
00056 typedef unsigned long    u32;
00057 typedef unsigned __int64 u64;
00058 
00059 #ifndef _SIZE_T_DEFINED
00060 # ifdef _WIN64
00061 typedef unsigned __int64 size_t;
00062 # else
00063 typedef unsigned int     size_t;
00064 # endif
00065 # define _SIZE_T_DEFINED
00066 #endif
00067 
00068 
00069 #else // WIN32
00070 #ifdef HAVE_CONFIG_H
00071 
00072 #include 
00073 
00074 #ifdef HAVE_STDLIB_H
00075 # include 
00076 #endif
00077 
00078 #ifdef HAVE_STDIO_H
00079 # include 
00080 #endif
00081 
00082 #if HAVE_DIRENT_H
00083 # include 
00084 # define NAMELEN(dirent) strlen((dirent)->d_name)
00085 #else
00086 # define dirent direct
00087 # define NAMELEN(dirent) (dirent)->d_namelen
00088 # if HAVE_SYS_NDIR_H
00089 # include 
00090 # endif
00091 # if HAVE_SYS_DIR_H
00092 # include 
00093 # endif
00094 # if HAVE_NDIR_H
00095 # include 
00096 # endif
00097 #endif
00098 
00099 #if STDC_HEADERS
00100 # include 
00101 #else
00102 # if !HAVE_STRCHR
00103 # define strchr index
00104 # define strrchr rindex
00105 # endif
00106 char *strchr(), *strrchr();
00107 # if !HAVE_MEMCPY
00108 # define memcpy(d, s, n) bcopy((s), (d), (n))
00109 # define memove(d, s, n) bcopy((s), (d), (n))
00110 # endif
00111 #endif
00112 
00113 #if HAVE_MEMORY_H
00114 # include 
00115 #endif
00116 
00117 #ifndef __WIN32__
00118 # define stricmp strcasecmp
00119 #endif
00120 
00121 #if HAVE_INTTYPES_H
00122 # include 
00123 #endif
00124 
00125 #if HAVE_STDINT_H
00126 # include 
00127 typedef uint8_t            u8;
00128 typedef uint16_t           u16;
00129 typedef uint32_t           u32;
00130 typedef uint64_t           u64;
00131 #else
00132 typedef unsigned char      u8;
00133 typedef unsigned short     u16;
00134 typedef unsigned int       u32;
00135 typedef unsigned long long u64;
00136 #endif
00137 
00138 #if HAVE_SYS_STAT_H
00139 # include 
00140 #endif
00141 
00142 #if HAVE_SYS_TYPES_H
00143 # include 
00144 #endif
00145 
00146 #if HAVE_UNISTD_H
00147 # include 
00148 #endif
00149 
00150 #define _MAX_PATH 255
00151 
00152 #if HAVE_ENDIAN_H
00153 # include 
00154 # ifndef __LITTLE_ENDIAN
00155 # ifdef _LITTLE_ENDIAN
00156 # define __LITTLE_ENDIAN _LITTLE_ENDIAN
00157 # define __LITTLE_ENDIAN _LITTLE_ENDIAN
00158 # define __BIG_ENDIAN _BIG_ENDIAN
00159 # define __PDP_ENDIAN _PDP_ENDIAN
00160 # else
00161 # error  does not define __LITTLE_ENDIAN etc.
00162 # endif
00163 # endif
00164 #else
00165 # define __LITTLE_ENDIAN 1234
00166 # define __BIG_ENDIAN 4321
00167 # define __PDP_ENDIAN 3412
00168 # if WORDS_BIGENDIAN
00169 # define __BYTE_ORDER __BIG_ENDIAN
00170 # else
00171 # define __BYTE_ORDER __LITTLE_ENDIAN
00172 # endif
00173 #endif
00174 
00175 #else // HAVE_CONFIG_H
00176 
00177 #include 
00178 #include 
00179 #include 
00180 #include 
00181 #include 
00182 #include 
00183 #include 
00184 #include 
00185 #include 
00186 #include 
00187 
00188 #include 
00189 
00190 #define _MAX_PATH 255
00191 #define stricmp strcasecmp
00192 #define _stat stat
00193 
00194 typedef   unsigned char        u8;
00195 typedef   unsigned short       u16;
00196 typedef   unsigned int         u32;
00197 typedef   unsigned long long   u64;
00198 
00199 #endif
00200 #endif
00201 
00202 #ifdef WIN32
00203  #define PATHSEP "\\"
00204  #define ALTPATHSEP "/"
00205 
00206  #ifdef UNICODE
00207  #define stat _wstati64 /* _stat64 */ /* 'i64' so that files >= 4GB can be processed, was: #define stat _stat */
00208  #define struct_stat struct _stati64 /* _stati64 */ /* _stat64 */ /* 'i64' so that files >= 4GB can be processed, was: #define stat _stat */
00209     // should probably rewrite these as inline functions instead of macros - but watch out for the '.c_str()' usage on tmp strings:
00210  #define utf8_string_to_native_char_array(x) ::UTF8_to_UTF16(x).c_str()
00211  #define utf8_char_array_to_native_char_array(x) ::UTF8_to_UTF16(x, strlen(x)).c_str()
00212  #define utf8_string_to_cout_parameter(x) ::UTF8_string_to_cout_string(x)
00213  #define native_char_array_to_utf8_string(x) ::UTF16_to_UTF8(x)
00214  #define native_char_array_to_utf8_char_array(x) ::UTF16_to_UTF8(x).c_str()
00215  #else
00216  #define stat _stati64 /* _stat64 */ /* 'i64' so that files >= 4GB can be processed, was: #define stat _stat */
00217  #define struct_stat struct _stati64 /* _stati64 */ /* _stat64 */ /* 'i64' so that files >= 4GB can be processed, was: #define stat _stat */
00218     // should probably rewrite these as inline functions instead of macros - but watch out for the '.c_str()' usage on tmp strings:
00219  #define utf8_string_to_native_char_array(x) x.c_str()
00220  #define utf8_char_array_to_native_char_array(x) x
00221  #define utf8_string_to_cout_parameter(x) x
00222  #define native_char_array_to_utf8_string(x) string(x)
00223  #define native_char_array_to_utf8_char_array(x) x
00224  #endif
00225 #else
00226  #define PATHSEP "/"
00227  #define ALTPATHSEP "\\"
00228 
00229  #define struct_stat struct stat
00230   // should probably rewrite these as inline functions instead of macros - but watch out for the '.c_str()' usage on tmp strings:
00231  #define utf8_string_to_native_char_array(x) x.c_str()
00232  #define utf8_char_array_to_native_char_array(x) x
00233  #define utf8_string_to_cout_parameter(x) x
00234  #define native_char_array_to_utf8_string(x) string(x)
00235  #define native_char_array_to_utf8_char_array(x) x
00236 
00237   typedef char TCHAR;
00238  #define _tcschr strchr
00239 #endif
00240 
00241 // Return type of par2cmdline
00242 typedef enum Result
00243 {
00244   eSuccess                     = 0,
00245 
00246   eRepairPossible              = 1,  // Data files are damaged and there is
00247                                      // enough recovery data available to
00248                                      // repair them.
00249 
00250   eRepairNotPossible           = 2,  // Data files are damaged and there is
00251                                      // insufficient recovery data available
00252                                      // to be able to repair them.
00253 
00254   eInvalidCommandLineArguments = 3,  // There was something wrong with the
00255                                      // command line arguments
00256 
00257   eInsufficientCriticalData    = 4,  // The PAR2 files did not contain sufficient
00258                                      // information about the data files to be able
00259                                      // to verify them.
00260 
00261   eRepairFailed                = 5,  // Repair completed but the data files
00262                                      // still appear to be damaged.
00263 
00264 
00265   eFileIOError                 = 6,  // An error occured when accessing files
00266   eLogicError                  = 7,  // In internal error occurred
00267   eMemoryError                 = 8,  // Out of memory
00268 
00269 } Result;
00270 
00271 #define LONGMULTIPLY
00272 
00273 // STL includes
00274 #include 
00275 #include 
00276 #include 
00277 #include 
00278 #include 
00279 
00280 #include 
00281 #include 
00282 #include 
00283 
00284 #include 
00285 
00286 #include 
00287 
00288 using namespace std;
00289 
00290 #ifdef WIN32
00291   extern wstring UTF8_to_UTF16(const char* utf8_str, size_t utf8_length);
00292   extern wstring UTF8_to_UTF16(const string& utf8);
00293   extern string  UTF8_string_to_cout_string(const string& utf8);
00294   extern string  UTF16_to_UTF8(const wchar_t* utf16);
00295 #endif
00296 
00297 #ifdef offsetof
00298 #undef offsetof
00299 #endif
00300 #define offsetof(TYPE, MEMBER) ((size_t) ((char*)(&((TYPE *)1)->MEMBER) - (char*)1))
00301 
00302 #if WANT_CONCURRENT
00303  #include "tbb/task_scheduler_init.h"
00304  #include "tbb/atomic.h"
00305  #include "tbb/concurrent_hash_map.h"
00306  #include "tbb/concurrent_vector.h"
00307  #include "tbb/tick_count.h"
00308  #include "tbb/blocked_range.h"
00309  #include "tbb/parallel_for.h"
00310  #include "tbb/mutex.h"
00311 
00312   class CTimeInterval {
00313   public:
00314     CTimeInterval(const std::string& label) :
00315       _label(label), _start(tbb::tick_count::now()), _done(false) {}
00316     ~CTimeInterval(void) {  emit();  }
00317     void  suppress_emission(void) { _done = true; }
00318     void  emit(void) {
00319       if (!_done) {
00320         _done  =  true;
00321         tbb::tick_count  end  =  tbb::tick_count::now();
00322         cout << _label << " took " << (end-_start).seconds() << " seconds." << endl;
00323       }
00324     }
00325   private:
00326     std::string     _label;
00327     tbb::tick_count _start;
00328     bool            _done;
00329   };
00330 
00331  #define WANT_PARALLEL_WHILE 1
00332 
00333   // using parallel_for() causes disk thrashing because it partitions
00334   // the files into large groups, each of which is iterated over by one
00335   // thread. For example, 100 files on a 2 CPU machine would be processed
00336   // in a manner like this:
00337   //
00338   // thread #1: file 1, file 2, file 3, ..., file 50
00339   // thread #2: file 51, file 52, file 53, ..., file 100
00340   //
00341   // using parallel_while allows the threads to iterate over the files
00342   // in sequential order; in effect, a FIFO queue is being implemented.
00343 
00344  #include "tbb/parallel_while.h"
00345  #include "tbb_misc.h" // for tbb::DetectNumberOfWorkers(); it's a pity that tbb_misc.h is not in /include/tbb/
00346 
00347   // === begin generic classes for use with parallel_while() ===
00348 
00349   template <typename ITEM>
00350   class item_stream {
00351     ITEM _item;
00352   public:
00353     bool pop_if_present( ITEM& item ) {
00354       if ( _item ) {
00355         item = _item;
00356         _item = get_next_item(_item);
00357         return true;
00358       } else {
00359         return false;
00360       }
00361     }
00362 
00363     item_stream(ITEM root_item) : _item(root_item) {}
00364   };
00365 
00366   template <typename BODY>
00367   class incrementing_parallel_while : public tbb::parallel_while {
00368     tbb::atomic _nexti;
00369   public:
00370     incrementing_parallel_while(size_t start_i = 0) { _nexti = start_i; }
00371     size_t get_next_i(void) const { return _nexti; }
00372 
00373     std::pair increment_next_i_up_to(size_t max_i) {
00374       size_t i = 1 + _nexti.fetch_and_increment();
00375       if (i < max_i)
00376         return std::pair(true, i);
00377 
00378       _nexti.fetch_and_decrement();
00379       return std::pair(false, 0);
00380     }
00381   };
00382 
00383   template <typename BODY>
00384   class incrementing_parallel_while_with_max : public incrementing_parallel_while {
00385     size_t _maxi;
00386   public:
00387     incrementing_parallel_while_with_max(size_t start_i, size_t max_i) :
00388       incrementing_parallel_while(start_i), _maxi(max_i) { assert(start_i != max_i); }
00389 
00390     std::pair increment_next_i(void)
00391     { return incrementing_parallel_while::increment_next_i_up_to(_maxi); }
00392   };
00393 
00394   template <typename ITEM, template <typename ITEM> class PARALLEL_WHILE = incrementing_parallel_while>
00395   class item_applier {
00396     PARALLEL_WHILE< item_applier >& _w;
00397   public:
00398     void operator()( ITEM item ) const {
00399       apply_to_item(item);
00400       if (!add_next_items(_w, item))
00401         dispose_item(item);
00402     }
00403 
00404     typedef ITEM argument_type;
00405     item_applier(PARALLEL_WHILE< item_applier >& w) : _w(w) {}
00406   };
00407 
00408   template <typename ITEM>
00409   static
00410   ITEM*
00411   get_next_item(ITEM* item)
00412   {
00413     return item->next();
00414   }
00415 
00416   template <typename ITEM>
00417   static
00418   void
00419   apply_to_item(ITEM* item)
00420   {
00421     item->apply();
00422   }
00423 
00424   template <typename ITEM>
00425   static
00426   void
00427   dispose_item(ITEM* item)
00428   {
00429     delete item;
00430   }
00431 
00432   // returns true if item was recycled into w (so caller should not dispose of item),
00433   // and false if item was not recycled (so caller MUST dispose of item)
00434   template <typename ITEM>
00435   static
00436   bool
00437   add_next_items(
00438     incrementing_parallel_while_with_max< item_applier00439                   incrementing_parallel_while_with_max> >& w,
00440     ITEM* item)
00441   {
00442     const size_t n = item->is_first() ? tbb::DetectNumberOfWorkers() : 1;
00443 
00444     bool res = false;
00445     std::pair pr(w.increment_next_i());
00446     if (pr.first && item->set_next_i(pr.second)) {
00447       w.add(item);
00448       res = true;
00449 
00450       for (size_t i = 1; i != n; ++i) {
00451         pr = w.increment_next_i();
00452         if (pr.first) {
00453           ITEM* clone = item->clone_for_next_i(pr.second);
00454           if (clone) {
00455             w.add(clone);
00456             continue;
00457           }
00458         }
00459         break;
00460       }
00461     }
00462 
00463     return res;
00464   }
00465 
00466   template <typename ITEM, template <typename ITEM> class PARALLEL_WHILE>
00467   static
00468   void
00469   parallel_while(ITEM* first_item, size_t item_count)
00470   {
00471     std::auto_ptr item(first_item); // capture first_item for exception safety
00472     PARALLEL_WHILE< item_applier >
00473                                         w(0, item_count);
00474     item_applier body(w);
00475     item_stream                  stream(item.release());
00476     w.run( stream, body );
00477   }
00478 
00479   // === end generic classes for use with parallel_while() ===
00480 
00481   enum { ALL_SERIAL, CHECKSUM_SERIALLY_BUT_PROCESS_CONCURRENTLY, ALL_CONCURRENT };
00482 #endif
00483 
00484 #include "letype.h"
00485 // par2cmdline includes
00486 
00487 #include "galois.h"
00488 #include "crc.h"
00489 #include "md5.h"
00490 #include "par2fileformat.h"
00491 #include "commandline.h"
00492 #include "reedsolomon.h"
00493 
00494 #include "diskfile.h"
00495 #include "datablock.h"
00496 
00497 #include "criticalpacket.h"
00498 #include "par2creatorsourcefile.h"
00499 
00500 #include "mainpacket.h"
00501 #include "creatorpacket.h"
00502 #include "descriptionpacket.h"
00503 #include "verificationpacket.h"
00504 #include "recoverypacket.h"
00505 
00506 #include "par2repairersourcefile.h"
00507 
00508 #include "filechecksummer.h"
00509 #include "verificationhashtable.h"
00510 
00511 #include "par2creator.h"
00512 #include "par2repairer.h"
00513 
00514 #include "par1fileformat.h"
00515 #include "par1repairersourcefile.h"
00516 #include "par1repairer.h"
00517 
00518 // Heap checking
00519 #ifdef _MSC_VER
00520 #define _CRTDBG_MAP_ALLOC
00521 #include 
00522 #define DEBUG_NEW new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
00523 #endif
00524 
00525 #endif // __PARCMDLINE_H__
00526 

Generated on Sun Oct 12 01:45:30 2008 for NNTPGrab by  1.5.4