예제 #1
0
 private void ScanChunk()
 {
     _chunkFiles = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);
     foreach (string file in _archive.AllFileNames())
     {
         string[] parts = file.Split('\\');
         if (parts.Length > 2)
         {
             if (ExtraFolders.Contains(parts[0]) || Conditionals.Any(cf => cf.Folder.Equals(parts[0], StringComparison.InvariantCultureIgnoreCase)))
             {
                 parts = parts.Skip(1).ToArray();
             }
             else
             {
                 continue;
             }
         }
         if (parts.Length < 2)
         {
             continue;
         }
         int chunk = parts[1].IndexOf(".chunk.", StringComparison.InvariantCultureIgnoreCase);
         if (chunk > 0)
         {
             _chunkFiles.Add(parts[0] + "\\" + parts[1].Substring(0, chunk));
         }
     }
     System.Diagnostics.Debug.WriteLine("    Finished scan for chunks, found " + String.Join(",", _chunkFiles));
 }
예제 #2
0
파일: IrosArc.cs 프로젝트: professorlust/7h
 public static void Create(IrosArc original, IrosArc updated, System.IO.Stream patchOutput, CompressType compress, Action<double, string> onProgress) {
     string[] deleted = original.AllFileNames()
         .Except(updated.AllFileNames(), StringComparer.InvariantCultureIgnoreCase)
         .ToArray();
     List<IrosArc.ArchiveCreateEntry> pentries = new List<IrosArc.ArchiveCreateEntry>();
     if (deleted.Any()) {
         onProgress(0, "Adding deleted entries");
         byte[] deldata = System.Text.Encoding.Unicode.GetBytes(String.Join("\n", deleted));
         pentries.Add(new IrosArc.ArchiveCreateEntry() {
             Filename = "%IrosPatch:Deleted",
             GetData = () => deldata
         });
     }
     foreach (string newFile in updated.AllFileNames().Except(original.AllFileNames(), StringComparer.InvariantCultureIgnoreCase)) {
         onProgress(0, "Adding new entries");
         string fn = newFile;
         pentries.Add(new IrosArc.ArchiveCreateEntry() {
             Filename = fn,
             GetData = () => updated.GetBytes(fn)
         });
     }
     foreach (string check in original.AllFileNames().Intersect(updated.AllFileNames())) {
         onProgress(0, "Checking " + check);
         if (!Same(original.GetBytes(check), updated.GetBytes(check))) {
             string fn = check;
             pentries.Add(new IrosArc.ArchiveCreateEntry() {
                 Filename = fn,
                 GetData = () => updated.GetBytes(fn)
             });
         }
     }
     IrosArc.Create(patchOutput, pentries, ArchiveFlags.Patch, compress, onProgress);
 }
예제 #3
0
파일: IrosArc.cs 프로젝트: rodriada000/7h
        public void ApplyPatch(IrosArc patch, Action <double, string> onProgress)
        {
            int currentDirSize = _entries.Sum(e => e.GetSize());

            byte[] deldata = patch.GetBytes("%IrosPatch:Deleted");
            if (deldata != null)
            {
                string[] delfile = System.Text.Encoding.Unicode.GetString(deldata).Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string del in delfile)
                {
                    RuntimeLog.Write("Removing file {0} from archive", del);
                    _entries.RemoveAll(e => e.Filename.Equals(del, StringComparison.InvariantCultureIgnoreCase));
                }
                onProgress(0, "Removed " + delfile.Length + " deleted files");
            }
            int count = 0;
            var files = patch.AllFileNames().Where(s => !s.StartsWith("%")).ToArray();

            foreach (string file in files)
            {
                var    patchEntry = patch._lookup[file];
                byte[] data       = new byte[patchEntry.Length];
                patch._data.Position = patchEntry.Offset;
                patch._data.Read(data, 0, data.Length);
                if (HasFile(file))   //update existing
                {
                    RuntimeLog.Write("File {0} is already in archive...", file);
                    DirectoryEntry exist = _lookup[file];
                    if (exist.Length >= data.Length)   //put data in same position, woo
                    {
                        RuntimeLog.Write("...updating in place");
                        _data.Position = exist.Offset;
                    }
                    else     //stick at end of file
                    {
                        _data.Position = _data.Length;
                        exist.Offset   = _data.Position;
                        RuntimeLog.Write("...size increase: writing to end of file");
                    }
                    _data.Write(data, 0, data.Length);
                    exist.Length = data.Length;
                    exist.Flags  = patchEntry.Flags;
                }
                else     //new file, just append
                {
                    RuntimeLog.Write("File {0} is new, appending", file);
                    DirectoryEntry de = new DirectoryEntry()
                    {
                        Filename = file,
                        Flags    = patchEntry.Flags,
                        Length   = patchEntry.Length,
                        Offset   = _data.Length
                    };
                    _data.Position = de.Offset;
                    _data.Write(data, 0, data.Length);
                    _entries.Add(de);
                    _lookup[file] = de;
                }

                count++;
                onProgress(1.0 * count / files.Length, "Processed " + file);
            }
            int newDirSize = _entries.Sum(e => e.GetSize());

            if (newDirSize <= currentDirSize)
            {
                RuntimeLog.Write("Directory will fit in existing location");
                _data.Position = _header.Directory;
            }
            else
            {
                RuntimeLog.Write("Directory size increase, appending");
                if (_data.Length >= int.MaxValue)   //write forwarder
                {
                    _data.Position = _header.Directory;
                    _data.WriteInt(-1);
                    _data.WriteLong(_data.Length);
                    _data.Position = _data.Length;
                }
                else     //write direct location
                {
                    _header.Directory = (int)_data.Length;
                    _data.Position    = _header.Directory;
                }
            }
            _data.WriteInt(_entries.Count);
            foreach (var e in _entries)
            {
                e.Save(_data);
            }
            _header.Version = MAX_VERSION;
            _data.Position  = 0;
            _header.Save(_data);
            onProgress(1.0, "Wrote directory");
        } //TODO: track blank spaces in file and reuse where possible...