22 #include "C4Version.h"
51 printf(
"Version: %d.%d ", head.
Ver1, head.
Ver2);
56 printf(
"File CRC: %u (%X) ", crc, crc);
58 printf(
"File CRC: <error accessing file> ");
61 printf(
"Contents CRC: %u (%X)\n", contents_crc, contents_crc);
64 size_t max_fn_len = 0;
67 if (filter ==
nullptr ||
WildcardMatch(filter, entry->FileName))
68 max_fn_len = std::max(max_fn_len, strlen(entry->FileName));
72 size_t file_count = 0;
73 size_t byte_count = 0;
76 if (filter !=
nullptr && !
WildcardMatch(filter, entry->FileName))
79 printf(
"%*s %8u Bytes",
83 if (entry->ChildGroup != 0)
85 if (entry->Executable != 0)
86 printf(
" (Executable)");
90 byte_count += entry->Size;
92 printf(
"%lu Entries, %lu Bytes\n", (
unsigned long)file_count, (
unsigned long)byte_count);
98 int indent = indent_level * 4;
100 printf(
"%*sHead.id: '%s'\n", indent,
"", head.
Id);
101 printf(
"%*sHead.Ver1: %d\n", indent,
"", head.
Ver1);
102 printf(
"%*sHead.Ver2: %d\n", indent,
"", head.
Ver2);
103 printf(
"%*sHead.Entries: %d\n", indent,
"", head.
Entries);
106 printf(
"%*sEntry '%s':\n", indent,
"", p->FileName);
107 printf(
"%*s Packed: %d\n", indent,
"", p->Packed);
108 printf(
"%*s ChildGroup: %d\n", indent,
"", p->ChildGroup);
109 printf(
"%*s Size: %d\n", indent,
"", p->Size);
110 printf(
"%*s Offset: %d\n", indent,
"", p->Offset);
111 printf(
"%*s Executable: %d\n", indent,
"", p->Executable);
112 if (p->ChildGroup != 0)
126 bool fDeleteGroup =
false;
132 char * szFilename = strdup(FilenamePar);
133 size_t len = strlen(szFilename);
136 LogF(
"Group: %s", szFilename);
139 if (hGroup.
Open(szFilename,
true))
152 if (argv[iArg][0] ==
'-')
155 switch (argv[iArg][1])
162 if ((iArg + 1 >= argc) || (argv[iArg + 1][0] ==
'-'))
164 fprintf(stderr,
"Missing argument for sort command\n");
169 hGroup.
Sort(argv[iArg + 1]);
175 if ((iArg + 1 >= argc) || (argv[iArg + 1][0] ==
'-'))
191 fprintf(stderr,
"Closing failed: %s\n", hGroup.
GetError());
196 fprintf(stderr,
"Pack failed\n");
199 else if (!hGroup.
Open(szFilename))
201 fprintf(stderr,
"Reopen failed: %s\n", hGroup.
GetError());
206 if ((iArg + 1 >= argc))
208 fprintf(stderr,
"Pack failed: too few arguments\n");
216 fprintf(stderr,
"Closing failed: %s\n", hGroup.
GetError());
220 fprintf(stderr,
"Destination Clear failed\n");
226 fprintf(stderr,
"Pack failed\n");
230 szFilename = strdup(argv[iArg]);
232 if (!hGroup.
Open(szFilename))
234 fprintf(stderr,
"Reopen failed: %s\n", hGroup.
GetError());
239 LogF(
"Unpacking...");
243 fprintf(stderr,
"Closing failed: %s\n", hGroup.
GetError());
248 fprintf(stderr,
"Unpack failed\n");
251 else if (!hGroup.
Open(szFilename))
253 fprintf(stderr,
"Reopen failed: %s\n", hGroup.
GetError());
262 fprintf(stderr,
"Closing failed: %s\n", hGroup.
GetError());
267 fprintf(stderr,
"Unpack failed\n");
270 else if (!hGroup.
Open(szFilename))
272 fprintf(stderr,
"Reopen failed: %s\n", hGroup.
GetError());
277 if ((iArg + 3 >= argc) || (argv[iArg + 1][0] ==
'-')
278 || (argv[iArg + 2][0] ==
'-')
279 || (argv[iArg + 3][0] ==
'-'))
281 fprintf(stderr,
"Update generation failed: too few arguments\n");
289 fprintf(stderr,
"Closing failed: %s\n", hGroup.
GetError());
292 else if (!Upd.
MakeUpdate(argv[iArg + 1], argv[iArg + 2], szFilename, argv[iArg + 3]))
294 fprintf(stderr,
"Update generation failed.\n");
297 else if (!hGroup.
Open(szFilename))
299 fprintf(stderr,
"Reopen failed: %s\n", hGroup.
GetError());
308 Log(
"Applying update...");
309 unsigned long pid = 0;
310 bool have_pid =
false;
315 pid = strtoul(argv[iArg+1],
nullptr, 10);
323 {
if (argv[iArg][2]==
'd') fDeleteGroup =
true; }
325 fprintf(stderr,
"Update failed.\n");
335 fprintf(stderr,
"Unknown command: %s\n", argv[iArg]);
341 fprintf(stderr,
"Invalid parameter %s\n", argv[iArg]);
349 fprintf(stderr,
"Status: %s\n", hGroup.
GetError());
354 fprintf(stderr,
"Closing: %s\n", hGroup.
GetError());
366 fprintf(stderr,
"Status: %s\n", hGroup.
GetError());
376 wchar_t strModule[2048+1];
377 wchar_t strCommand[2048+1];
380 GetModuleFileNameW(
nullptr, strModule, 2048);
382 const char *strClasses =
383 "Clonk4.Definition;Clonk4.Folder;Clonk4.Group;Clonk4.Player;Clonk4.Scenario;Clonk4.Update;Clonk4.Weblink";
387 _snwprintf(strCommand, 2048, L
"\"%s\" \"%%1\" \"-u\"", strModule);
388 if (!SetRegShell(
GetWideChar(strClass), L
"MakeFolder", L
"C4Group Unpack", strCommand))
391 _snwprintf(strCommand, 2048, L
"\"%s\" \"%%1\" \"-x\"", strModule);
392 if (!SetRegShell(
GetWideChar(strClass), L
"ExplodeFolder", L
"C4Group Explode", strCommand))
396 const char *strClasses2 =
"Directory";
397 for (i = 0;
SCopySegment(strClasses2, i, strClass); i++)
400 _snwprintf(strCommand, 2048, L
"\"%s\" \"%%1\" \"-p\"", strModule);
401 if (!SetRegShell(
GetWideChar(strClass), L
"MakeGroupFile", L
"C4Group Pack", strCommand))
415 const char *strClasses =
416 "Clonk4.Definition;Clonk4.Folder;Clonk4.Group;Clonk4.Player;Clonk4.Scenario;Clonk4.Update;Clonk4.Weblink";
420 if (!RemoveRegShell(strClass,
"MakeFolder"))
423 if (!RemoveRegShell(strClass,
"ExplodeFolder"))
427 const char *strClasses2 =
"Directory";
428 for (i = 0;
SCopySegment(strClasses2, i, strClass); i++)
431 if (!RemoveRegShell(strClass,
"MakeGroupFile"))
439 int main(
int argc,
char *argv[])
443 setvbuf(stdout,
nullptr, _IOLBF, 0);
448 for (
int i = 1; i < argc; ++i)
451 if (argv[i][0] ==
'-')
477 std::string sep{
"\n=================================\n"};
479 if (license.path.substr(0, 7) !=
"planet/")
480 Log((sep + license.path +
": " + license.name + sep + license.content +
"\n").c_str());
485 fprintf(stderr,
"Unknown option %s\n", argv[i]);
501 LogF(
"OpenClonk C4Group %s", C4VERSION);
514 printf(
"Shell extensions registered.\n");
516 printf(
"Error registering shell extensions.\n");
522 printf(
"Shell extensions removed.\n");
524 printf(
"Error removing shell extensions.\n");
538 for (
int i = iFirstGroup; i < argc && argv[i][0] !=
'-'; ++i)
545 printf(
"Usage: c4group [options] group(s) command(s)\n\n");
546 printf(
"Commands: -l List\n");
547 printf(
" -x Explode\n");
548 printf(
" -u Unpack\n");
549 printf(
" -p Pack\n");
550 printf(
" -t [filename] Pack To\n");
551 printf(
" -y [ppid] Apply update (waiting for ppid to terminate first)\n");
552 printf(
" -g [source] [target] [title] Make update\n");
553 printf(
" -s Sort\n");
555 printf(
"Options: -v Verbose -r Recursive\n");
556 printf(
" -i Register shell -u Unregister shell\n");
557 printf(
" -x:<command> Execute shell command when done\n");
558 printf(
" -L Show licenses and exit\n");
560 printf(
"Examples: c4group pack.ocg -x\n");
561 printf(
" c4group update.ocu -g ver1.ocf ver2.ocf New_Version\n");
562 printf(
" c4group -i\n");
571 STARTUPINFOW startInfo;
572 ZeroMem(&startInfo,
sizeof(startInfo));
573 startInfo.cb =
sizeof(startInfo);
575 PROCESS_INFORMATION procInfo;
583 fprintf(stderr,
"Error forking.\n");
bool C4Group_ExplodeDirectory(const char *filename)
bool C4Group_PackDirectoryTo(const char *filename, const char *to_filename)
bool C4Group_PackDirectory(const char *filename)
void C4Group_SetSortList(const char **sort_list)
bool C4Group_UnpackDirectory(const char *filename)
int main(int argc, char *argv[])
bool EraseItemSafe(const char *szFilename)
void DisplayGroup(C4Group &grp, const char *filter=nullptr)
void PrintGroupInternals(C4Group &grp, int indent_level=0)
bool ProcessGroup(const char *FilenamePar)
int UnregisterShellExtensions()
int RegisterShellExtensions()
char strExecuteAtEnd[_MAX_PATH_LEN]
const std::vector< OCLicenseInfo > OCLicenses
bool Log(const char *szMessage)
bool LogF(const char *strMessage,...)
bool C4Group_ApplyUpdate(C4Group &hGroup, unsigned long ParentProcessID)
StdStrBuf::wchar_t_holder GetWideChar(const char *utf8, bool double_null_terminate=false)
bool GetFileCRC(const char *szFilename, uint32_t *pCRC32)
unsigned int SCharCount(char cTarget, const char *szInStr, const char *cpUntil)
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
std::enable_if< std::is_pod< T >::value >::type ZeroMem(T *lpMem, size_t dwSize)
bool SEqual(const char *szStr1, const char *szStr2)
bool EraseItem(const char *szItemName)
bool WildcardMatch(const char *szWildcard, const char *szString)
char * GetFilename(char *szPath)
int ForEachFile(const char *szDirName, bool(*fnCallback)(const char *))
const C4GroupEntry * GetFirstEntry() const
const C4GroupHeader & GetHeader() const
StdStrBuf GetFullName() const
unsigned int EntryCRC32(const char *wildcard=nullptr)
bool OpenAsChild(C4Group *mother, const char *entry_name, bool is_exclusive=false, bool do_create=false)
bool Sort(const char *list)
void SetStdOutput(bool log_status)
bool Open(const char *group_name, bool do_create=false)
bool MakeUpdate(const char *strFile1, const char *strFile2, const char *strUpdateFile, const char *strName=nullptr)
const char * getData() const