Пример #1
0
        private void CreateFci(long maxArchiveSize)
        {
            NativeMethods.FCI.CCAB ccab = new NativeMethods.FCI.CCAB();
            if (maxArchiveSize > 0 && maxArchiveSize < ccab.cb)
            {
                ccab.cb = Math.Max(
                    NativeMethods.FCI.MIN_DISK, (int)maxArchiveSize);
            }

            object maxFolderSizeOption = context.GetOption(
                "maxFolderSize", null);

            if (maxFolderSizeOption != null)
            {
                long maxFolderSize = Convert.ToInt64(
                    maxFolderSizeOption, CultureInfo.InvariantCulture);
                if (maxFolderSize > 0 && maxFolderSize < ccab.cbFolderThresh)
                {
                    ccab.cbFolderThresh = (int)maxFolderSize;
                }
            }

            maxCabBytes = ccab.cb;
            ccab.szCab  = context.GetArchiveName(0);
            if (ccab.szCab == null)
            {
                throw new FileNotFoundException(
                          "Cabinet name not provided by stream context.");
            }
            ccab.setID = (short)new Random().Next(
                Int16.MinValue, Int16.MaxValue + 1);
            CabNumbers[ccab.szCab] = 0;
            currentArchiveName     = ccab.szCab;
            totalArchives          = 1;
            CabStream = null;

            Erf.Clear();
            fciHandle = NativeMethods.FCI.Create(
                ErfHandle.AddrOfPinnedObject(),
                fciFilePlacedHandler,
                fciAllocMemHandler,
                fciFreeMemHandler,
                fciOpenStreamHandler,
                fciReadStreamHandler,
                fciWriteStreamHandler,
                fciCloseStreamHandler,
                fciSeekStreamHandler,
                fciDeleteFileHandler,
                fciGetTempFileHandler,
                ccab,
                IntPtr.Zero);
            CheckError(false);
        }
Пример #2
0
 protected override void Dispose(bool disposing)
 {
     try {
         if (disposing)
         {
             if (fciHandle != null)
             {
                 fciHandle.Dispose();
                 fciHandle = null;
             }
         }
     } finally {
         base.Dispose(disposing);
     }
 }
Пример #3
0
        public void Pack(
            IPackStreamContext streamContext,
            IEnumerable <string> files,
            long maxArchiveSize)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            if (files == null)
            {
                throw new ArgumentNullException("files");
            }

            lock (this) {
                try {
                    context = streamContext;

                    ResetProgressData();

                    CreateFci(maxArchiveSize);

                    foreach (string file in files)
                    {
                        FileAttributes attributes;
                        DateTime       lastWriteTime;
                        Stream         fileStream = context.OpenFileReadStream(
                            file,
                            out attributes,
                            out lastWriteTime);
                        if (fileStream != null)
                        {
                            totalFileBytes += fileStream.Length;
                            totalFiles++;
                            context.CloseFileReadStream(file, fileStream);
                        }
                    }

                    long uncompressedBytesInFolder = 0;
                    currentFileNumber = -1;

                    foreach (string file in files)
                    {
                        FileAttributes attributes;
                        DateTime       lastWriteTime;
                        Stream         fileStream = context.OpenFileReadStream(
                            file, out attributes, out lastWriteTime);
                        if (fileStream == null)
                        {
                            continue;
                        }

                        if (fileStream.Length >= NativeMethods.FCI.MAX_FOLDER)
                        {
                            throw new NotSupportedException(String.Format(
                                                                CultureInfo.InvariantCulture,
                                                                "File {0} exceeds maximum file size " +
                                                                "for cabinet format.",
                                                                file));
                        }

                        if (uncompressedBytesInFolder > 0)
                        {
                            // Automatically create a new folder if this file
                            // won't fit in the current folder.
                            bool nextFolder = uncompressedBytesInFolder
                                              + fileStream.Length >= NativeMethods.FCI.MAX_FOLDER;

                            // Otherwise ask the client if it wants to
                            // move to the next folder.
                            if (!nextFolder)
                            {
                                object nextFolderOption = streamContext.GetOption(
                                    "nextFolder",
                                    new object[] { file, currentFolderNumber });
                                nextFolder = Convert.ToBoolean(
                                    nextFolderOption, CultureInfo.InvariantCulture);
                            }

                            if (nextFolder)
                            {
                                FlushFolder();
                                uncompressedBytesInFolder = 0;
                            }
                        }

                        if (currentFolderTotalBytes > 0)
                        {
                            currentFolderTotalBytes = 0;
                            currentFolderNumber++;
                            uncompressedBytesInFolder = 0;
                        }

                        currentFileName = file;
                        currentFileNumber++;

                        currentFileTotalBytes     = fileStream.Length;
                        currentFileBytesProcessed = 0;
                        OnProgress(ArchiveProgressType.StartFile);

                        uncompressedBytesInFolder += fileStream.Length;

                        AddFile(
                            file,
                            fileStream,
                            attributes,
                            lastWriteTime,
                            false,
                            CompressionLevel);
                    }

                    FlushFolder();
                    FlushCabinet();
                } finally {
                    if (CabStream != null)
                    {
                        context.CloseArchiveWriteStream(
                            currentArchiveNumber,
                            currentArchiveName,
                            CabStream);
                        CabStream = null;
                    }

                    if (FileStream != null)
                    {
                        context.CloseFileReadStream(
                            currentFileName, FileStream);
                        FileStream = null;
                    }
                    context = null;

                    if (fciHandle != null)
                    {
                        fciHandle.Dispose();
                        fciHandle = null;
                    }
                }
            }
        }