Esempio n. 1
0
        public ParResult Process(Par2LibraryArguments args)
        {
            Par2Library.targetPath = args.targetPath;

            List <string> inputFiles    = new List <string>(args.inputFiles);
            List <string> recoveryFiles = new List <string>(args.recoveryFiles);

            if (args.version == ParVersion.Par1)
            {
                return(Par1Library().Process(inputFiles, recoveryFiles, args.action));
            }

            if (args.action != ParAction.ParCreate)
            {
                GetRecoveryFiles(recoveryFiles);
            }

            switch (args.action)
            {
            case ParAction.ParCreate:
                return(Create(ref inputFiles, ref recoveryFiles, args));

            case ParAction.ParRepair:
                return(Repair(ref inputFiles, ref recoveryFiles));

            case ParAction.ParVerify:
                return(Verify(ref inputFiles, ref recoveryFiles));
            }

            return(ParResult.LogicError);
        }
Esempio n. 2
0
        public ParResult Process(Par2LibraryArguments args)
        {
            Par2Library.targetPath = args.targetPath;

            List<string> inputFiles = new List<string>(args.inputFiles);
            List<string> recoveryFiles = new List<string>(args.recoveryFiles);

            if (args.version == ParVersion.Par1)
                return Par1Library().Process(inputFiles, recoveryFiles, args.action);

            if (args.action != ParAction.ParCreate)
                GetRecoveryFiles(recoveryFiles);

            switch (args.action)
            {
                case ParAction.ParCreate:
                    return Create(ref inputFiles, ref recoveryFiles, args);
                case ParAction.ParRepair:
                    return Repair(ref inputFiles, ref recoveryFiles);
                case ParAction.ParVerify:
                    return Verify(ref inputFiles, ref recoveryFiles);
            }

            return ParResult.LogicError;
        }
Esempio n. 3
0
        /*
         Repair commandline /mt- /rf:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests\EntLib50.par2" /action:ParRepair

         *
         * Create commandline /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50.chm" /action:ParCreate /rbc:10 /mtcpu- /mtio-
         *
         *
         * /mtio- /mtcpu- /a:ParVerify /rf:C:\Users\Jerome\Documents\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss\5150.par2
         *
         * /if:"C:\Users\Jerome\Documents\BigCreate\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss.part01.rar" /if:"C:\Users\Jerome\Documents\BigCreate\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss.part02.rar" /if:"C:\Users\Jerome\Documents\BigCreate\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss.part03.rar" /action:ParCreate /rbc:10 /mtcpu- /mtio-
         *
         * /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50.chm" /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50_copy.chm" /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50_copy2.chm" /rbc:30 /mtio- /mtcpu+ /action:ParCreate
         *
         */
        static void Main(string[] args)
        {
            Par2LibraryArguments par2args = new Par2LibraryArguments();

            if (!Parser.ParseArgumentsWithUsage(args, par2args))
                return;

            switch (par2args.action)
            {
                case ParAction.ParCreate:
                    if (par2args.inputFiles.Length == 0 || (par2args.redundancy == -1 && par2args.recoveryblockcount == -1))
                    {
                        Parser.ArgumentsUsage(par2args.GetType());
                        return;
                    }
                    break;
                case ParAction.ParVerify:
                case ParAction.ParRepair:
                    if (par2args.recoveryFiles.Length == 0)
                    {
                        Parser.ArgumentsUsage(par2args.GetType());
                        return;
                    }
                    break;
            }

            Par2Library library = new Par2Library(par2args.multithreadCPU, par2args.multithreadIO);

            List<string> inputFiles = new List<string>(par2args.inputFiles);
            List<string> recoveryFiles = new List<string>(par2args.recoveryFiles);

            if (string.IsNullOrEmpty(par2args.targetPath))
            {
                if (par2args.action == ParAction.ParCreate)
                    par2args.targetPath = Path.GetDirectoryName(par2args.inputFiles[0]);
                else
                    par2args.targetPath = Path.GetDirectoryName(par2args.recoveryFiles[0]);
            }

            #if TimeTrack
            DateTime startTime = DateTime.Now;
            #endif
            ParResult result = library.Process(par2args);
            #if TimeTrack
            DateTime endTime = DateTime.Now;
            TimeSpan duration = endTime - startTime;

            System.Console.WriteLine("Duration : {0}h{1}m{2}s{3}ms", duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);
            #endif

            System.Console.WriteLine("Par2NET result : {0}", result);
            //recoveryFiles.Add(@"C:\USERS\Projects\__Perso\Par2NET\Par2NET\Tests\EntLib50.vol10+10.PAR2");
            //recoveryFiles.Add(@"C:\Documents and Settings\Jerome\My Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests\EntLib50.vol10+10.PAR2");
            //recoveryFiles.Add(@"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests\EntLib50.vol10+10.PAR2");

            //ParResult result = library.Process(ParVersion.Par2, inputFiles, recoveryFiles, ParAction.ParVerify, @"C:\Documents and Settings\Jerome\My Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests");
            //ParResult result = library.Process(ParVersion.Par2, inputFiles, recoveryFiles, ParAction.ParRepair, @"C:\Documents and Settings\Jerome\My Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests");
        }
Esempio n. 4
0
        private void FullChainRoot_InnerDomain(string[] args, bool needRepair)
        {
            Par2LibraryArguments par2args = new Par2LibraryArguments();

            if (!Parser.ParseArgumentsWithUsage(args, par2args))
            {
                return;
            }

            switch (par2args.action)
            {
            case ParAction.ParCreate:
                if (par2args.inputFiles.Length == 0 || (par2args.redundancy == -1 && par2args.recoveryblockcount == -1))
                {
                    Parser.ArgumentsUsage(par2args.GetType());
                    return;
                }
                break;

            case ParAction.ParVerify:
            case ParAction.ParRepair:
                if (par2args.recoveryFiles.Length == 0)
                {
                    Parser.ArgumentsUsage(par2args.GetType());
                    return;
                }
                break;
            }

            Par2Library library = new Par2Library(par2args.multithreadCPU, par2args.multithreadIO);

            List <string> inputFiles    = new List <string>(par2args.inputFiles);
            List <string> recoveryFiles = new List <string>(par2args.recoveryFiles);

            if (string.IsNullOrEmpty(par2args.targetPath))
            {
                if (par2args.action == ParAction.ParCreate)
                {
                    par2args.targetPath = Path.GetDirectoryName(par2args.inputFiles[0]);
                }
                else
                {
                    par2args.targetPath = Path.GetDirectoryName(par2args.recoveryFiles[0]);
                }
            }

            ParResult result = library.Process(par2args);

            Assert.AreEqual <ParResult>(ParResult.Success, result);
        }
Esempio n. 5
0
        public ParResult Process(Par2LibraryArguments args)
        {
            List<string> inputFiles = new List<string>(args.inputFiles);
            List<string> recoveryFiles = new List<string>(args.recoveryFiles);

            switch (args.action)
            {
                case ParAction.ParCreate:
                    return Create(ref inputFiles, ref recoveryFiles);
                case ParAction.ParRepair:
                    return Repair(ref inputFiles, ref recoveryFiles);
                case ParAction.ParVerify:
                    return Verify(ref inputFiles, ref recoveryFiles);
            }

            return ParResult.LogicError;
        }
Esempio n. 6
0
        public ParResult Process(Par2LibraryArguments args)
        {
            List <string> inputFiles    = new List <string>(args.inputFiles);
            List <string> recoveryFiles = new List <string>(args.recoveryFiles);

            switch (args.action)
            {
            case ParAction.ParCreate:
                return(Create(ref inputFiles, ref recoveryFiles));

            case ParAction.ParRepair:
                return(Repair(ref inputFiles, ref recoveryFiles));

            case ParAction.ParVerify:
                return(Verify(ref inputFiles, ref recoveryFiles));
            }

            return(ParResult.LogicError);
        }
Esempio n. 7
0
        public static MainPacket Create(Par2LibraryArguments args)
        {
            MainPacket tmpPacket = new MainPacket();
            tmpPacket.header = new PacketHeader();
            tmpPacket.header.setid = new byte[16];
            tmpPacket.header.magic = Par2FileReader.packet_magic;
            tmpPacket.header.type = Par2FileReader.mainpacket_type;

            tmpPacket.blocksize = (ulong)args.blocksize;
            tmpPacket.recoverablefilecount = (uint)args.inputFiles.Length;
            tmpPacket.fileids = new List<byte[]>();
            tmpPacket.header.length = (ulong)(tmpPacket.GetSize() + (16 * sizeof(byte) * args.inputFiles.Length));

            // setid calculation and fileids insertion will occur in Par2RecoverySet.OpenSourceFiles method

            System.Threading.Tasks.Task.Factory.StartNew((b) =>
            {
                //FastCRC32.FastCRC32 crc32 = new FastCRC32.FastCRC32((ulong)b);
                FastCRC32.FastCRC32 crc32 = FastCRC32.FastCRC32.GetCRC32Instance((ulong)b);
            }, tmpPacket.blocksize);

            return tmpPacket;
        }
Esempio n. 8
0
        public static MainPacket Create(Par2LibraryArguments args)
        {
            MainPacket tmpPacket = new MainPacket();

            tmpPacket.header       = new PacketHeader();
            tmpPacket.header.setid = new byte[16];
            tmpPacket.header.magic = Par2FileReader.packet_magic;
            tmpPacket.header.type  = Par2FileReader.mainpacket_type;

            tmpPacket.blocksize            = (ulong)args.blocksize;
            tmpPacket.recoverablefilecount = (uint)args.inputFiles.Length;
            tmpPacket.fileids       = new List <byte[]>();
            tmpPacket.header.length = (ulong)(tmpPacket.GetSize() + (16 * sizeof(byte) * args.inputFiles.Length));

            // setid calculation and fileids insertion will occur in Par2RecoverySet.OpenSourceFiles method

            System.Threading.Tasks.Task.Factory.StartNew((b) =>
            {
                //FastCRC32.FastCRC32 crc32 = new FastCRC32.FastCRC32((ulong)b);
                FastCRC32.FastCRC32 crc32 = FastCRC32.FastCRC32.GetCRC32Instance((ulong)b);
            }, tmpPacket.blocksize);

            return(tmpPacket);
        }
Esempio n. 9
0
        private ParResult Create(ref List<string> inputFiles, ref List<string> recoveryFiles, Par2LibraryArguments args)
        {
            // Initialize the base par2 filename if not set in the command line
            if (args.par2filename == string.Empty)
            {
                //args.par2filename = args.inputFiles[0] + ".par2";
                args.par2filename = args.inputFiles[0];
            }

            Par2RecoverySet recoverySet = new Par2RecoverySet(args.multithreadCPU, args.multithreadIO, args);

            // Compute block size from block count or vice versa depending on which was
            // specified on the command line
            if (!recoverySet.ComputeBlockSizeAndBlockCount(ref inputFiles))
                return ParResult.InvalidCommandLineArguments;

            // Determine how many recovery blocks to create based on the source block
            // count and the requested level of redundancy.
            if (recoverySet.redundancy > 0 && !recoverySet.ComputeRecoveryBlockCount(recoverySet.redundancy))
                return ParResult.InvalidCommandLineArguments;

            // Determine how much recovery data can be computed on one pass
            if (!recoverySet.CalculateProcessBlockSize(GetMemoryLimit()))
                return ParResult.LogicError;

            // Determine how many recovery files to create.
            if (!recoverySet.ComputeRecoveryFileCount())
                return ParResult.InvalidCommandLineArguments;

            //if (noiselevel > CommandLine::nlQuiet)
            //{
            // Display information.
            Console.WriteLine("Block size: " + recoverySet.MainPacket.blocksize);
            Console.WriteLine("Source file count: " + recoverySet.SourceFiles.Count);
            Console.WriteLine("Source block count: " + recoverySet.sourceblockcount);
            if (recoverySet.redundancy > 0 || recoverySet.recoveryblockcount == 0)
                Console.WriteLine("Redundancy: " + recoverySet.redundancy + '%');
            Console.WriteLine("Recovery block count: " + recoverySet.recoveryblockcount);
            Console.WriteLine("Recovery file count: " + recoverySet.recoveryfilecount);
            //}

            // Open all of the source files, compute the Hashes and CRC values, and store
            // the results in the file verification and file description packets.
            if (!recoverySet.OpenSourceFiles(ref inputFiles))
                return ParResult.FileIOError;

            // Create the main packet and determine the setid to use with all packets
            //if (!recoverySet.CreateMainPacket(Par2LibraryArguments args))
            //  return ParResult.LogicError;

            recoverySet.criticalpackets.Add(recoverySet.MainPacket);

            // Create the creator packet.
            if (!recoverySet.CreateCreatorPacket())
                return ParResult.LogicError;

            // Initialise all of the source blocks ready to start reading data from the source files.
            if (!recoverySet.CreateSourceBlocks())
                return ParResult.LogicError;

            // Create all of the output files and allocate all packets to appropriate file offets.
            if (!recoverySet.InitialiseOutputFiles(args.par2filename))
                return ParResult.FileIOError;

            if (recoverySet.recoveryblockcount > 0)
            {
                // Allocate memory buffers for reading and writing data to disk.
                if (!recoverySet.AllocateBuffers())
                    return ParResult.MemoryError;

                // Compute the Reed Solomon matrix
                if (!recoverySet.ComputeRSMatrix())  //TODO: Unify and switch for Create and Verify/Repair
                    return ParResult.LogicError;

                // Set the total amount of data to be processed.
                /*progress = 0;
                totaldata = blocksize * sourceblockcount * recoveryblockcount;
                previouslyReportedFraction = -10000000;	// Big negative*/

                //Par2RecoverySet.LogArrayToFile<byte>(@"outputbuffer.before.createparityblocks.log", recoverySet.outputbuffer);

                // Start at an offset of 0 within a block.
                ulong blockoffset = 0;
                while (blockoffset < recoverySet.MainPacket.blocksize) // Continue until the end of the block.
                {
                    // Work out how much data to process this time.
                    ulong blocklength = (ulong)Math.Min(recoverySet.chunksize, recoverySet.MainPacket.blocksize - blockoffset);

                    // Read source data, process it through the RS matrix and write it to disk.
                    if (!recoverySet.ProcessData(blockoffset, blocklength))
                        return ParResult.FileIOError;

                    blockoffset += blocklength;
                }

                //Par2RecoverySet.LogArrayToFile<byte>(@"outputbuffer.after.createparityblocks.log", recoverySet.outputbuffer);

                //if (noiselevel > CommandLine::nlQuiet)
                //  cout << "Writing recovery packets" << endl;

                // Finish computation of the recovery packets and write the headers to disk.
                if (!recoverySet.WriteRecoveryPacketHeaders())
                    return ParResult.FileIOError;

                // Finish computing the full file hash values of the source files
                if (!recoverySet.FinishFileHashComputation())
                    return ParResult.LogicError;
            }

            // Fill in all remaining details in the critical packets.
            if (!recoverySet.FinishCriticalPackets())
                return ParResult.LogicError;

            //if (noiselevel > CommandLine::nlQuiet)
            //  cout << "Writing verification packets" << endl;

            // Write all other critical packets to disk.
            if (!recoverySet.WriteCriticalPackets())
                return ParResult.FileIOError;

            // Close all files.
            if (!recoverySet.CloseFiles())
                return ParResult.FileIOError;

            //if (noiselevel > CommandLine::nlSilent)
            //  cout << "Done" << endl;

            return ParResult.Success;
        }
Esempio n. 10
0
        private void FullChainRoot_InnerDomain(string[] args, bool needRepair)
        {
            Par2LibraryArguments par2args = new Par2LibraryArguments();

            if (!Parser.ParseArgumentsWithUsage(args, par2args))
                return;

            switch (par2args.action)
            {
                case ParAction.ParCreate:
                    if (par2args.inputFiles.Length == 0 || (par2args.redundancy == -1 && par2args.recoveryblockcount == -1))
                    {
                        Parser.ArgumentsUsage(par2args.GetType());
                        return;
                    }
                    break;
                case ParAction.ParVerify:
                case ParAction.ParRepair:
                    if (par2args.recoveryFiles.Length == 0)
                    {
                        Parser.ArgumentsUsage(par2args.GetType());
                        return;
                    }
                    break;
            }

            Par2Library library = new Par2Library(par2args.multithreadCPU, par2args.multithreadIO);

            List<string> inputFiles = new List<string>(par2args.inputFiles);
            List<string> recoveryFiles = new List<string>(par2args.recoveryFiles);

            if (string.IsNullOrEmpty(par2args.targetPath))
            {
                if (par2args.action == ParAction.ParCreate)
                    par2args.targetPath = Path.GetDirectoryName(par2args.inputFiles[0]);
                else
                    par2args.targetPath = Path.GetDirectoryName(par2args.recoveryFiles[0]);
            }

            ParResult result = library.Process(par2args);

            Assert.AreEqual<ParResult>(ParResult.Success, result);
        }
Esempio n. 11
0
        private ParResult Create(ref List <string> inputFiles, ref List <string> recoveryFiles, Par2LibraryArguments args)
        {
            // Initialize the base par2 filename if not set in the command line
            if (args.par2filename == string.Empty)
            {
                //args.par2filename = args.inputFiles[0] + ".par2";
                args.par2filename = args.inputFiles[0];
            }

            Par2RecoverySet recoverySet = new Par2RecoverySet(args.multithreadCPU, args.multithreadIO, args);

            // Compute block size from block count or vice versa depending on which was
            // specified on the command line
            if (!recoverySet.ComputeBlockSizeAndBlockCount(ref inputFiles))
            {
                return(ParResult.InvalidCommandLineArguments);
            }

            // Determine how many recovery blocks to create based on the source block
            // count and the requested level of redundancy.
            if (recoverySet.redundancy > 0 && !recoverySet.ComputeRecoveryBlockCount(recoverySet.redundancy))
            {
                return(ParResult.InvalidCommandLineArguments);
            }

            // Determine how much recovery data can be computed on one pass
            if (!recoverySet.CalculateProcessBlockSize(GetMemoryLimit()))
            {
                return(ParResult.LogicError);
            }

            // Determine how many recovery files to create.
            if (!recoverySet.ComputeRecoveryFileCount())
            {
                return(ParResult.InvalidCommandLineArguments);
            }

            //if (noiselevel > CommandLine::nlQuiet)
            //{
            // Display information.
            Console.WriteLine("Block size: " + recoverySet.MainPacket.blocksize);
            Console.WriteLine("Source file count: " + recoverySet.SourceFiles.Count);
            Console.WriteLine("Source block count: " + recoverySet.sourceblockcount);
            if (recoverySet.redundancy > 0 || recoverySet.recoveryblockcount == 0)
            {
                Console.WriteLine("Redundancy: " + recoverySet.redundancy + '%');
            }
            Console.WriteLine("Recovery block count: " + recoverySet.recoveryblockcount);
            Console.WriteLine("Recovery file count: " + recoverySet.recoveryfilecount);
            //}

            // Open all of the source files, compute the Hashes and CRC values, and store
            // the results in the file verification and file description packets.
            if (!recoverySet.OpenSourceFiles(ref inputFiles))
            {
                return(ParResult.FileIOError);
            }

            // Create the main packet and determine the setid to use with all packets
            //if (!recoverySet.CreateMainPacket(Par2LibraryArguments args))
            //  return ParResult.LogicError;

            recoverySet.criticalpackets.Add(recoverySet.MainPacket);

            // Create the creator packet.
            if (!recoverySet.CreateCreatorPacket())
            {
                return(ParResult.LogicError);
            }

            // Initialise all of the source blocks ready to start reading data from the source files.
            if (!recoverySet.CreateSourceBlocks())
            {
                return(ParResult.LogicError);
            }

            // Create all of the output files and allocate all packets to appropriate file offets.
            if (!recoverySet.InitialiseOutputFiles(args.par2filename))
            {
                return(ParResult.FileIOError);
            }

            if (recoverySet.recoveryblockcount > 0)
            {
                // Allocate memory buffers for reading and writing data to disk.
                if (!recoverySet.AllocateBuffers())
                {
                    return(ParResult.MemoryError);
                }

                // Compute the Reed Solomon matrix
                if (!recoverySet.ComputeRSMatrix())  //TODO: Unify and switch for Create and Verify/Repair
                {
                    return(ParResult.LogicError);
                }

                // Set the total amount of data to be processed.

                /*progress = 0;
                 * totaldata = blocksize * sourceblockcount * recoveryblockcount;
                 * previouslyReportedFraction = -10000000;	// Big negative*/

                //Par2RecoverySet.LogArrayToFile<byte>(@"outputbuffer.before.createparityblocks.log", recoverySet.outputbuffer);

                // Start at an offset of 0 within a block.
                ulong blockoffset = 0;
                while (blockoffset < recoverySet.MainPacket.blocksize) // Continue until the end of the block.
                {
                    // Work out how much data to process this time.
                    ulong blocklength = (ulong)Math.Min(recoverySet.chunksize, recoverySet.MainPacket.blocksize - blockoffset);

                    // Read source data, process it through the RS matrix and write it to disk.
                    if (!recoverySet.ProcessData(blockoffset, blocklength))
                    {
                        return(ParResult.FileIOError);
                    }

                    blockoffset += blocklength;
                }

                //Par2RecoverySet.LogArrayToFile<byte>(@"outputbuffer.after.createparityblocks.log", recoverySet.outputbuffer);

                //if (noiselevel > CommandLine::nlQuiet)
                //  cout << "Writing recovery packets" << endl;

                // Finish computation of the recovery packets and write the headers to disk.
                if (!recoverySet.WriteRecoveryPacketHeaders())
                {
                    return(ParResult.FileIOError);
                }

                // Finish computing the full file hash values of the source files
                if (!recoverySet.FinishFileHashComputation())
                {
                    return(ParResult.LogicError);
                }
            }

            // Fill in all remaining details in the critical packets.
            if (!recoverySet.FinishCriticalPackets())
            {
                return(ParResult.LogicError);
            }

            //if (noiselevel > CommandLine::nlQuiet)
            //  cout << "Writing verification packets" << endl;

            // Write all other critical packets to disk.
            if (!recoverySet.WriteCriticalPackets())
            {
                return(ParResult.FileIOError);
            }

            // Close all files.
            if (!recoverySet.CloseFiles())
            {
                return(ParResult.FileIOError);
            }

            //if (noiselevel > CommandLine::nlSilent)
            //  cout << "Done" << endl;

            return(ParResult.Success);
        }
Esempio n. 12
0
        /*
         * Repair commandline /mt- /rf:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests\EntLib50.par2" /action:ParRepair
         *
         *
         * Create commandline /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50.chm" /action:ParCreate /rbc:10 /mtcpu- /mtio-
         *
         *
         * /mtio- /mtcpu- /a:ParVerify /rf:C:\Users\Jerome\Documents\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss\5150.par2
         *
         * /if:"C:\Users\Jerome\Documents\BigCreate\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss.part01.rar" /if:"C:\Users\Jerome\Documents\BigCreate\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss.part02.rar" /if:"C:\Users\Jerome\Documents\BigCreate\5150.Rue.Des.Ormes.LIMITED.FRENCHDVDRIP.XVID.AC3-TBoss.part03.rar" /action:ParCreate /rbc:10 /mtcpu- /mtio-
         *
         * /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50.chm" /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50_copy.chm" /if:"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\CreateTests\EntLib50_copy2.chm" /rbc:30 /mtio- /mtcpu+ /action:ParCreate
         *
         */
        static void Main(string[] args)
        {
            Par2LibraryArguments par2args = new Par2LibraryArguments();

            if (!Parser.ParseArgumentsWithUsage(args, par2args))
            {
                return;
            }

            switch (par2args.action)
            {
            case ParAction.ParCreate:
                if (par2args.inputFiles.Length == 0 || (par2args.redundancy == -1 && par2args.recoveryblockcount == -1))
                {
                    Parser.ArgumentsUsage(par2args.GetType());
                    return;
                }
                break;

            case ParAction.ParVerify:
            case ParAction.ParRepair:
                if (par2args.recoveryFiles.Length == 0)
                {
                    Parser.ArgumentsUsage(par2args.GetType());
                    return;
                }
                break;
            }

            Par2Library library = new Par2Library(par2args.multithreadCPU, par2args.multithreadIO);

            List <string> inputFiles    = new List <string>(par2args.inputFiles);
            List <string> recoveryFiles = new List <string>(par2args.recoveryFiles);

            if (string.IsNullOrEmpty(par2args.targetPath))
            {
                if (par2args.action == ParAction.ParCreate)
                {
                    par2args.targetPath = Path.GetDirectoryName(par2args.inputFiles[0]);
                }
                else
                {
                    par2args.targetPath = Path.GetDirectoryName(par2args.recoveryFiles[0]);
                }
            }

#if TimeTrack
            DateTime startTime = DateTime.Now;
#endif
            ParResult result = library.Process(par2args);
#if TimeTrack
            DateTime endTime  = DateTime.Now;
            TimeSpan duration = endTime - startTime;

            System.Console.WriteLine("Duration : {0}h{1}m{2}s{3}ms", duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);
#endif

            System.Console.WriteLine("Par2NET result : {0}", result);
            //recoveryFiles.Add(@"C:\USERS\Projects\__Perso\Par2NET\Par2NET\Tests\EntLib50.vol10+10.PAR2");
            //recoveryFiles.Add(@"C:\Documents and Settings\Jerome\My Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests\EntLib50.vol10+10.PAR2");
            //recoveryFiles.Add(@"C:\Users\Jerome\Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests\EntLib50.vol10+10.PAR2");

            //ParResult result = library.Process(ParVersion.Par2, inputFiles, recoveryFiles, ParAction.ParVerify, @"C:\Documents and Settings\Jerome\My Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests");
            //ParResult result = library.Process(ParVersion.Par2, inputFiles, recoveryFiles, ParAction.ParRepair, @"C:\Documents and Settings\Jerome\My Documents\Visual Studio 2010\Projects\Par2NET\Par2NET\Tests");
        }