OpenClonk
C4Group.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Handles group files */
19 
20 #ifndef INC_C4Group
21 #define INC_C4Group
22 
23 #ifdef HAVE_IO_H
24 #include <io.h>
25 #endif
26 #include "c4group/CStdFile.h"
27 
28 // C4Group-Rewind-warning:
29 // The current C4Group-implementation cannot handle random file access very well,
30 // because all files are written within a single zlib-stream.
31 // For every out-of-order-file accessed a group-rewind must be performed, and every
32 // single file up to the accessed file unpacked. As a workaround, all C4Groups are
33 // packed in a file order matching the reading order of the engine.
34 // If the reading order doesn't match the packing order, and a rewind has to be performed,
35 // a warning is issued in Debug-builds of the engine. But since some components require
36 // random access because they are loaded on-demand at runtime (e.g. global sounds), the
37 // warning may be temp disabled for those files using C4GRP_DISABLE_REWINDWARN and
38 // C4GRP_ENABLE_REWINDWARN. A ref counter keeps track of nested calls to those functions.
39 //
40 // If you add any new components to scenario or definition files, remember to adjust the
41 // sort order lists in C4Components.h accordingly, and enforce a reading order for that
42 // component.
43 //
44 // Maybe some day, someone will write a C4Group-implementation that is probably capable of
45 // random access...
46 #ifdef _DEBUG
47 extern int iC4GroupRewindFilePtrNoWarn;
48 #define C4GRP_DISABLE_REWINDWARN ++iC4GroupRewindFilePtrNoWarn;
49 #define C4GRP_ENABLE_REWINDWARN --iC4GroupRewindFilePtrNoWarn;
50 #else
51 #define C4GRP_DISABLE_REWINDWARN ;
52 #define C4GRP_ENABLE_REWINDWARN ;
53 #endif
54 
55 const int C4GroupFileVer1 = 1;
56 const int C4GroupFileVer2 = 2;
57 
58 const int C4GroupMaxError = 100;
59 
60 const int32_t C4GroupSwapThreshold = 10 * 1024 * 1024;
61 
62 #define C4GroupFileID "RedWolf Design GrpFolder"
63 
64 bool C4Group_TestIgnore(const char *filename);
65 void C4Group_SetTempPath(const char *path);
66 const char* C4Group_GetTempPath();
67 void C4Group_SetSortList(const char **sort_list);
68 void C4Group_SetProcessCallback(bool (*callback)(const char *, int));
69 bool C4Group_IsGroup(const char *filename);
70 bool C4Group_CopyItem(const char *source, const char *target, bool no_sorting = false, bool reset_attributes = false);
71 bool C4Group_MoveItem(const char *source, const char *target, bool no_sorting = false);
72 bool C4Group_DeleteItem(const char *item_name, bool do_recycle = false);
73 bool C4Group_PackDirectoryTo(const char *filename, const char *to_filename);
74 bool C4Group_PackDirectory(const char *filename);
75 bool C4Group_UnpackDirectory(const char *filename);
76 bool C4Group_ExplodeDirectory(const char *filename);
77 bool C4Group_ReadFile(const char *filename, char **data, size_t *size);
78 
79 extern const char *C4CFN_FLS[];
80 
81 #pragma pack (push, 1)
82 
84 {
85  char Id[24+4] = C4GroupFileID;
88  int Entries = 0;
89  char Reserved[164] = { 0 };
90 };
91 
93 {
94  char FileName[260] = { 0 };
95  int32_t Packed = 0;
96  int32_t ChildGroup = 0;
97  int32_t Size = 0;
98  int32_t Offset = 0;
99  int32_t Reserved1 = 0;
100  int32_t Reserved2 = 0;
101  char Reserved3 = '\0';
102  unsigned int Reserved4 = 0;
103  char Executable = '\0';
104  BYTE Buffer[26] = { 0 };
105 };
106 
107 #pragma pack (pop)
108 
110 {
111 public:
112  ~C4GroupEntry();
113 
115  {
120  };
121 
122 public:
123  char DiskPath[_MAX_PATH_LEN] = { 0 };
125  bool DeleteOnDisk = false;
126  bool HoldBuffer = false;
127  bool BufferIsStdbuf = false;
128  bool NoSort = false;
129  BYTE *MemoryBuffer = nullptr;
130  C4GroupEntry *Next = nullptr;
131 public:
132  void Set(const DirectoryIterator & directories, const char * path);
133 };
134 
135 class C4Group : public CStdStream
136 {
137  struct P;
138  std::unique_ptr<P> p;
139 public:
140  C4Group();
141  ~C4Group() override;
142  C4Group(C4Group &&) = default;
143  C4Group &operator=(C4Group &&) = default;
144 
145 protected:
146  // C4Update requires these to be available by a subclass (C4GroupEx)
148  C4GroupEntry *GetEntry(const char *entry_name);
149  void Clear();
150 
151 public:
152  bool Open(const char *group_name, bool do_create = false);
153  bool Close();
154  bool Save(bool reopen);
155  bool OpenAsChild(C4Group *mother, const char *entry_name, bool is_exclusive = false, bool do_create = false);
156  bool OpenChild(const char* entry_name);
157  bool OpenMother();
158  bool Add(const char *filename, const char *entry_name);
159  bool Add(const char *entry_name, void *buffer, int size, bool add_as_child = false, bool hold_buffer = false, bool is_executable = false);
160  bool Add(const char *entry_name, StdBuf &buffer, bool add_as_child = false, bool hold_buffer = false, bool is_executable = false);
161  bool Add(const char *entry_name, StdStrBuf &buffer, bool add_as_child = false, bool hold_buffer = false, bool is_executable = false);
162  bool Merge(const char *folders);
163  bool Move(const char *filename, const char *entry_name);
164  bool Extract(const char *files, const char *destination = nullptr, const char *exclude = nullptr);
165  bool ExtractEntry(const char *filename, const char *destination = nullptr);
166  bool Delete(const char *files, bool recursive = false);
167  bool DeleteEntry(const char *filename, bool do_recycle = false);
168  bool Rename(const char *filename, const char *new_name);
169  bool Sort(const char *list);
170  bool SortByList(const char **list, const char *filename = nullptr);
171  bool AccessEntry(const char *wildcard,
172  size_t *size = nullptr,
173  char *filename = nullptr,
174  bool needs_to_be_a_group = false);
175  bool AccessNextEntry(const char *wildcard,
176  size_t *size = nullptr,
177  char *filename = nullptr,
178  bool start_at_filename = false);
179  bool LoadEntry(const char *entry_name,
180  char **buffer,
181  size_t *size_info = nullptr,
182  int zeros_to_append = 0);
183  bool LoadEntry(const char *entry_name, StdBuf * buffer);
184  bool LoadEntry(const StdStrBuf & name, StdBuf * buffer) { return LoadEntry(name.getData(), buffer); }
185  bool LoadEntryString(const char *entry_name, StdStrBuf * buffer);
186  bool LoadEntryString(const StdStrBuf & name, StdStrBuf * buffer) { return LoadEntryString(name.getData(), buffer); }
187  bool FindEntry(const char *wildcard,
188  StdStrBuf *filename = nullptr,
189  size_t *size = nullptr);
190  bool FindEntry(const char *wildcard, char *filename)
191  {
192  StdStrBuf name;
193  bool found_entry = FindEntry(wildcard, &name);
194  if (filename)
195  {
196  SCopy(name.getData(), filename);
197  }
198  return found_entry;
199  }
200  bool FindNextEntry(const char *wildcard,
201  StdStrBuf *filename = nullptr,
202  size_t *size = nullptr,
203  bool start_at_filename = false);
204  bool FindNextEntry(const char *wildcard,
205  char *filename,
206  size_t *size = nullptr,
207  bool start_at_filename = false)
208  {
209  StdStrBuf name(start_at_filename ? filename : "");
210  bool found_entry = FindNextEntry(wildcard, &name, size, start_at_filename);
211  if (found_entry && filename)
212  {
213  SCopy(name.getData(),filename);
214  }
215  return found_entry;
216  }
217  bool Read(void *buffer, size_t size) override;
218  bool Advance(int offset) override;
219  void SetStdOutput(bool log_status);
220  void ResetSearch(bool reload_contents = false); // reset search pointer so calls to FindNextEntry find first entry again. if reload_contents is set, the file list for directories is also refreshed.
221  const char *GetError();
222  const char *GetName() const;
223  StdStrBuf GetFullName() const;
224  int EntryCount(const char *wildcard = nullptr);
225  size_t EntrySize(const char *wildcard = nullptr);
226  size_t AccessedEntrySize() const override; // retrieve size of last accessed entry
227  unsigned int EntryCRC32(const char *wildcard = nullptr);
228  bool IsOpen() const;
229  C4Group *GetMother();
230  bool IsPacked() const;
231  bool HasPackedMother() const;
232  bool SetNoSort(bool no_sorting);
233  int PreCacheEntries(const char *search_pattern, bool cache_previous = false); // pre-load entries to memory. return number of loaded entries.
234 
235  const C4GroupHeader &GetHeader() const;
236  const C4GroupEntry *GetFirstEntry() const;
237 
238 private:
239  void Init();
240  bool EnsureChildFilePtr(C4Group *child);
241  bool CloseExclusiveMother();
242  bool Error(const char *status_message);
243  bool OpenReal(const char *group_name);
244  bool OpenRealGrpFile();
245  bool SetFilePtr(int offset);
246  bool RewindFilePtr();
247  bool AdvanceFilePtr(int offset);
248  bool AddEntry(C4GroupEntry::EntryStatus status,
249  bool add_as_child,
250  const char *fname,
251  long size,
252  const char *entry_name = nullptr,
253  BYTE *buffer = nullptr,
254  bool delete_on_disk = false,
255  bool hold_buffer = false,
256  bool is_executable = false,
257  bool buffer_is_stdbuf = false);
258  bool AddEntryOnDisk(const char *filename, const char *entry_name = nullptr, bool move = false);
259  bool SetFilePtr2Entry(const char *entry_name, bool needs_to_be_a_group = false);
260  bool AppendEntry2StdFile(C4GroupEntry *entry, CStdFile &target);
261  C4GroupEntry *SearchNextEntry(const char *entry_name);
262  C4GroupEntry *GetNextFolderEntry();
263  uint32_t CalcCRC32(C4GroupEntry *entry);
264  void PreCacheEntry(C4GroupEntry *entry);
265 };
266 
267 #endif
char Id[24+4]
Definition: C4Group.h:85
const int32_t C4GroupSwapThreshold
Definition: C4Group.h:60
void C4Group_SetTempPath(const char *path)
Definition: C4Group.cpp:74
bool C4Group_ExplodeDirectory(const char *filename)
Definition: C4Group.cpp:470
const int C4GroupMaxError
Definition: C4Group.h:58
bool C4Group_PackDirectoryTo(const char *filename, const char *to_filename)
Definition: C4Group.cpp:292
const int C4GroupFileVer2
Definition: C4Group.h:56
bool C4Group_PackDirectory(const char *filename)
Definition: C4Group.cpp:371
const char * C4CFN_FLS[]
Definition: C4Group.cpp:32
void C4Group_SetSortList(const char **sort_list)
Definition: C4Group.cpp:69
char Reserved[164]
Definition: C4Group.h:89
bool C4Group_MoveItem(const char *source, const char *target, bool no_sorting=false)
Definition: C4Group.cpp:182
void C4Group_SetProcessCallback(bool(*callback)(const char *, int))
Definition: C4Group.cpp:64
bool C4Group_TestIgnore(const char *filename)
Definition: C4Group.cpp:92
bool C4Group_CopyItem(const char *source, const char *target, bool no_sorting=false, bool reset_attributes=false)
Definition: C4Group.cpp:115
bool C4Group_UnpackDirectory(const char *filename)
Definition: C4Group.cpp:401
const int C4GroupFileVer1
Definition: C4Group.h:55
bool C4Group_IsGroup(const char *filename)
Definition: C4Group.cpp:104
const char * C4Group_GetTempPath()
Definition: C4Group.cpp:87
bool C4Group_ReadFile(const char *filename, char **data, size_t *size)
Definition: C4Group.cpp:491
bool C4Group_DeleteItem(const char *item_name, bool do_recycle=false)
Definition: C4Group.cpp:255
#define C4GroupFileID
Definition: C4Group.h:62
int Entries
Definition: C4Group.h:88
#define _MAX_PATH_LEN
uint8_t BYTE
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
Definition: C4Group.h:110
bool DeleteOnDisk
Definition: C4Group.h:125
~C4GroupEntry()
Definition: C4Group.cpp:596
void Set(const DirectoryIterator &directories, const char *path)
Definition: C4Group.cpp:608
char DiskPath[_MAX_PATH_LEN]
Definition: C4Group.h:123
EntryStatus
Definition: C4Group.h:115
@ C4GRES_InGroup
Definition: C4Group.h:116
@ C4GRES_InMemory
Definition: C4Group.h:118
@ C4GRES_OnDisk
Definition: C4Group.h:117
@ C4GRES_Deleted
Definition: C4Group.h:119
bool NoSort
Definition: C4Group.h:128
EntryStatus Status
Definition: C4Group.h:124
bool BufferIsStdbuf
Definition: C4Group.h:127
BYTE * MemoryBuffer
Definition: C4Group.h:129
bool HoldBuffer
Definition: C4Group.h:126
C4GroupEntry * Next
Definition: C4Group.h:130
bool Rename(const char *filename, const char *new_name)
Definition: C4Group.cpp:1735
bool Read(void *buffer, size_t size) override
Definition: C4Group.cpp:1430
bool FindNextEntry(const char *wildcard, StdStrBuf *filename=nullptr, size_t *size=nullptr, bool start_at_filename=false)
Definition: C4Group.cpp:2217
const C4GroupEntry * GetFirstEntry() const
Definition: C4Group.cpp:2863
bool DeleteEntry(const char *filename, bool do_recycle=false)
Definition: C4Group.cpp:1695
bool HasPackedMother() const
Definition: C4Group.cpp:2543
bool Merge(const char *folders)
Definition: C4Group.cpp:1534
size_t EntrySize(const char *wildcard=nullptr)
Definition: C4Group.cpp:2333
const C4GroupHeader & GetHeader() const
Definition: C4Group.cpp:2861
bool IsPacked() const
Definition: C4Group.cpp:2541
bool Extract(const char *files, const char *destination=nullptr, const char *exclude=nullptr)
Definition: C4Group.cpp:1808
const char * GetName() const
Definition: C4Group.cpp:2309
void Clear()
Definition: C4Group.cpp:1173
size_t AccessedEntrySize() const override
Definition: C4Group.cpp:2352
bool AccessNextEntry(const char *wildcard, size_t *size=nullptr, char *filename=nullptr, bool start_at_filename=false)
Definition: C4Group.cpp:2140
bool FindEntry(const char *wildcard, char *filename)
Definition: C4Group.h:190
bool AccessEntry(const char *wildcard, size_t *size=nullptr, char *filename=nullptr, bool needs_to_be_a_group=false)
Definition: C4Group.cpp:2104
int EntryCount(const char *wildcard=nullptr)
Definition: C4Group.cpp:2314
StdStrBuf GetFullName() const
Definition: C4Group.cpp:2638
int PreCacheEntries(const char *search_pattern, bool cache_previous=false)
Definition: C4Group.cpp:2831
bool ExtractEntry(const char *filename, const char *destination=nullptr)
Definition: C4Group.cpp:1870
bool Add(const char *filename, const char *entry_name)
Definition: C4Group.cpp:1621
unsigned int EntryCRC32(const char *wildcard=nullptr)
Definition: C4Group.cpp:2354
C4Group & operator=(C4Group &&)=default
bool LoadEntry(const char *entry_name, char **buffer, size_t *size_info=nullptr, int zeros_to_append=0)
Definition: C4Group.cpp:2375
C4Group * GetMother()
Definition: C4Group.cpp:2536
bool Save(bool reopen)
Definition: C4Group.cpp:1031
bool OpenAsChild(C4Group *mother, const char *entry_name, bool is_exclusive=false, bool do_create=false)
Definition: C4Group.cpp:1952
bool SetNoSort(bool no_sorting)
Definition: C4Group.cpp:2552
C4GroupEntry * GetEntry(const char *entry_name)
Definition: C4Group.cpp:954
bool LoadEntry(const StdStrBuf &name, StdBuf *buffer)
Definition: C4Group.h:184
bool LoadEntryString(const char *entry_name, StdStrBuf *buffer)
Definition: C4Group.cpp:2430
bool IsOpen() const
Definition: C4Group.cpp:2373
C4Group()
Definition: C4Group.cpp:623
bool OpenChild(const char *entry_name)
Definition: C4Group.cpp:2765
const char * GetError()
Definition: C4Group.cpp:650
bool Sort(const char *list)
Definition: C4Group.cpp:2470
~C4Group() override
Definition: C4Group.cpp:639
void SetStdOutput(bool log_status)
Definition: C4Group.cpp:655
C4Group(C4Group &&)=default
void ResetSearch(bool reload_contents=false)
Definition: C4Group.cpp:1316
bool Close()
Definition: C4Group.cpp:971
bool Move(const char *filename, const char *entry_name)
Definition: C4Group.cpp:1633
bool Delete(const char *files, bool recursive=false)
Definition: C4Group.cpp:1645
bool FindNextEntry(const char *wildcard, char *filename, size_t *size=nullptr, bool start_at_filename=false)
Definition: C4Group.h:204
bool OpenMother()
Definition: C4Group.cpp:2803
C4GroupHeader Head
Definition: C4Group.h:147
bool SortByList(const char **list, const char *filename=nullptr)
Definition: C4Group.cpp:2566
bool FindEntry(const char *wildcard, StdStrBuf *filename=nullptr, size_t *size=nullptr)
Definition: C4Group.cpp:2211
bool Open(const char *group_name, bool do_create=false)
Definition: C4Group.cpp:660
bool Advance(int offset) override
Definition: C4Group.cpp:1410
bool LoadEntryString(const StdStrBuf &name, StdStrBuf *buffer)
Definition: C4Group.h:186
Definition: StdBuf.h:30
const char * getData() const
Definition: StdBuf.h:442
Definition: C4Group.h:93
char FileName[260]
Definition: C4Group.h:94
int32_t Size
Definition: C4Group.h:97
int32_t Packed
Definition: C4Group.h:95
BYTE Buffer[26]
Definition: C4Group.h:104
char Executable
Definition: C4Group.h:103
int32_t Reserved2
Definition: C4Group.h:100
int32_t Reserved1
Definition: C4Group.h:99
int32_t ChildGroup
Definition: C4Group.h:96
char Reserved3
Definition: C4Group.h:101
int32_t Offset
Definition: C4Group.h:98
unsigned int Reserved4
Definition: C4Group.h:102