2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS cabinet manager
4 * FILE: apps/cabman/main.cpp
5 * PURPOSE: Main program
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 21/03-2001 Created
16 #include <reactos/buildno.h>
22 DWORD DebugTraceLevel = MIN_TRACE;
23 //DWORD DebugTraceLevel = MID_TRACE;
24 //DWORD DebugTraceLevel = MAX_TRACE;
29 #define CM_VERSION KERNEL_VERSION_STR
32 LPTSTR Pad(LPTSTR Str, CHAR PadChar, UINT Length)
34 * FUNCTION: Pads a string with a character to make a given length
36 * Str = Pointer to string to pad
37 * PadChar = Character to pad with
38 * Length = Disired length of string
42 * Str must be at least Length + 1 bytes
50 memcpy(&Str[Length - Len], Str, Len + 1);
51 memset(Str, PadChar, Length - Len);
57 LPTSTR Date2Str(LPTSTR Str, WORD Date)
59 * FUNCTION: Converts a DOS style date to a string
61 * Str = Pointer to destination string
62 * Date = DOS style date
70 Str[0] = (CHAR)('0' + ((Date & 0x01E0) >> 5) / 10);
71 Str[1] = (CHAR)('0' + ((Date & 0x01E0) >> 5) % 10);
74 Str[3] = (CHAR)('0' + (Date & 0x001F) / 10);
75 Str[4] = (CHAR)('0' + (Date & 0x001F) % 10);
78 dw = 1980 + ((Date & 0xFE00) >> 9);
79 Str[6] = (CHAR)('0' + dw / 1000); dw %= 1000;
80 Str[7] = (CHAR)('0' + dw / 100); dw %= 100;
81 Str[8] = (CHAR)('0' + dw / 10); dw %= 10;
82 Str[9] = (CHAR)('0' + dw % 10);
88 LPTSTR Time2Str(LPTSTR Str, WORD Time)
90 * FUNCTION: Converts a DOS style time to a string
92 * Str = Pointer to destination string
93 * Time = DOS style time
102 Hour = ((Time & 0xF800) >> 11);
109 Str[0] = (CHAR)('0' + Hour / 10);
111 Str[1] = (CHAR)('0' + Hour % 10);
114 Str[3] = (CHAR)('0' + ((Time & 0x07E0) >> 5) / 10);
115 Str[4] = (CHAR)('0' + ((Time & 0x07E0) >> 5) % 10);
118 dw = 2 * (Time & 0x001F);
119 Str[6] = (CHAR)('0' + dw / 10);
120 Str[7] = (CHAR)('0' + dw % 10);
122 Str[8] = PM? 'p' : 'a';
128 LPTSTR Attr2Str(LPTSTR Str, WORD Attr)
130 * FUNCTION: Converts attributes to a string
132 * Str = Pointer to destination string
139 if (Attr & CAB_ATTRIB_ARCHIVE)
145 if (Attr & CAB_ATTRIB_HIDDEN)
151 if (Attr & CAB_ATTRIB_READONLY)
157 if (Attr & CAB_ATTRIB_SYSTEM)
169 CCABManager::CCABManager()
171 * FUNCTION: Default constructor
175 Mode = CM_MODE_DISPLAY;
176 PromptOnOverwrite = TRUE;
180 CCABManager::~CCABManager()
182 * FUNCTION: Default destructor
188 VOID CCABManager::Usage()
190 * FUNCTION: Display usage information on screen
193 printf("ReactOS Cabinet Manager - Version %s\n\n", CM_VERSION);
194 printf("CABMAN [/D | /E] [/A] [/L dir] [/Y] cabinet [filename ...]\n");
195 printf("CABMAN /C dirfile\n");
196 printf(" cabinet Cabinet file.\n");
197 printf(" filename Name of the file to extract from the cabinet.\n");
198 printf(" Wild cards and multiple filenames\n");
199 printf(" (separated by blanks) may be used.\n\n");
200 printf(" dirfile Name of the directive file to use.\n\n");
203 printf(" /A Process ALL cabinets. Follows cabinet chain\n");
204 printf(" starting in first cabinet mentioned.\n");
205 printf(" /C Create cabinet.\n");
206 printf(" /D Display cabinet directory.\n");
207 printf(" /E Extract files from cabinet.\n");
208 printf(" /L dir Location to place extracted files\n");
209 printf(" (default is current directory).\n");
210 printf(" /Y Do not prompt before overwriting an existing file.\n\n");
214 BOOL CCABManager::ParseCmdline(INT argc, PCHAR argv[])
216 * FUNCTION: Parse command line arguments
218 * argc = Number of arguments on command line
219 * argv = Pointer to list of command line arguments
221 * TRUE if command line arguments was successfully parsed, false if not
226 BOOL FoundCabinet = FALSE;
228 ShowUsage = (argc < 2);
230 for (i = 1; i < argc; i++) {
231 if (argv[i][0] == '/') {
232 switch (argv[i][1]) {
234 case 'A': ProcessAll = TRUE; break;
236 case 'C': Mode = CM_MODE_CREATE; break;
238 case 'D': Mode = CM_MODE_DISPLAY; break;
240 case 'E': Mode = CM_MODE_EXTRACT; break;
243 if (argv[i][2] == ' ') {
245 SetDestinationPath((LPTSTR)&argv[i][0]);
247 SetDestinationPath((LPTSTR)&argv[i][1]);
250 case 'Y': PromptOnOverwrite = FALSE; break;
252 printf("Bad parameter %s.\n", argv[i]);
256 if ((FoundCabinet) || (Mode == CM_MODE_CREATE)) {
257 /* FIXME: There may be many of these if Mode != CM_MODE_CREATE */
258 lstrcpy((LPTSTR)FileName, argv[i]);
260 SetCabinetName(argv[i]);
272 SelectCodec(CAB_CODEC_MSZIP);
278 VOID CCABManager::CreateCabinet()
280 * FUNCTION: Create cabinet
285 Status = Load((LPTSTR)&FileName);
286 if (Status != CAB_STATUS_SUCCESS) {
287 printf("Specified directive file could not be found: %s.\n", (LPTSTR)&FileName);
295 VOID CCABManager::DisplayCabinet()
297 * FUNCTION: Display cabinet contents
305 if (Open() == CAB_STATUS_SUCCESS) {
306 printf("Cabinet %s\n\n", GetCabinetName());
308 if (FindFirst("", &Search) == CAB_STATUS_SUCCESS) {
310 if (Search.File->FileControlID != CAB_FILE_CONTINUED) {
311 printf("%s ", Date2Str((LPTSTR)&Str, Search.File->FileDate));
312 printf("%s ", Time2Str((LPTSTR)&Str, Search.File->FileTime));
313 printf("%s ", Attr2Str((LPTSTR)&Str, Search.File->Attributes));
314 printf("%s ", Pad(itoa(Search.File->FileSize, (LPTSTR)&Str, 10), ' ', 13));
315 printf("%s\n", Search.FileName);
318 ByteCount += Search.File->FileSize;
320 } while (FindNext(&Search) == CAB_STATUS_SUCCESS);
328 Pad(itoa(FileCount, (LPTSTR)&Str, 10), ' ', 12));
334 Pad(itoa(ByteCount, (LPTSTR)&Str, 10), ' ', 12));
336 /* There should be at least one file in a cabinet */
337 printf("No files in cabinet.");
340 printf("Cannot not open file: %s\n", GetCabinetName());
344 VOID CCABManager::ExtractFromCabinet()
346 * FUNCTION: Extract file(s) from cabinet
352 if (Open() == CAB_STATUS_SUCCESS) {
353 printf("Cabinet %s\n\n", GetCabinetName());
355 if (FindFirst("", &Search) == CAB_STATUS_SUCCESS) {
357 switch (Status = ExtractFile(Search.FileName)) {
358 case CAB_STATUS_SUCCESS:
360 case CAB_STATUS_INVALID_CAB:
361 printf("Cabinet contains errors.\n");
363 case CAB_STATUS_UNSUPPCOMP:
364 printf("Cabinet uses unsupported compression type.\n");
366 case CAB_STATUS_CANNOT_WRITE:
367 printf("You've run out of free space on the destination volume or the volume is damaged.\n");
370 printf("Unspecified error code (%d).\n", (UINT)Status);
373 } while (FindNext(&Search) == CAB_STATUS_SUCCESS);
376 printf("Cannot not open file: %s.\n", GetCabinetName());
380 VOID CCABManager::Run()
382 * FUNCTION: Process cabinet
385 printf("ReactOS Cabinet Manager - Version %s\n\n", CM_VERSION);
388 case CM_MODE_CREATE: CreateCabinet(); break;
389 case CM_MODE_DISPLAY: DisplayCabinet(); break;
390 case CM_MODE_EXTRACT: ExtractFromCabinet(); break;
400 BOOL CCABManager::OnOverwrite(PCFFILE File,
403 * FUNCTION: Called when extracting a file and it already exists
405 * File = Pointer to CFFILE for file being extracted
406 * Filename = Pointer to buffer with name of file (full path)
408 * TRUE if the file should be overwritten, FALSE if not
413 if (Mode == CM_MODE_CREATE)
416 /* Should we prompt on overwrite? */
417 if (!PromptOnOverwrite)
420 /* Ask if file should be overwritten */
421 printf("Overwrite %s (Yes/No/All)? ", GetFileName(FileName));
427 case 'y': printf("%c\n", ch); return TRUE;
429 case 'n': printf("%c\n", ch); return FALSE;
431 case 'a': printf("%c\n", ch); PromptOnOverwrite = FALSE; return TRUE;
437 VOID CCABManager::OnExtract(PCFFILE File,
440 * FUNCTION: Called just before extracting a file
442 * File = Pointer to CFFILE for file being extracted
443 * FileName = Pointer to buffer with name of file (full path)
446 printf("Extracting %s\n", GetFileName(FileName));
451 VOID CCABManager::OnDiskChange(LPTSTR CabinetName,
454 * FUNCTION: Called when a new disk is to be processed
456 * CabinetName = Pointer to buffer with name of cabinet
457 * DiskLabel = Pointer to buffer with label of disk
460 printf("\nChanging to cabinet %s - %s\n\n", CabinetName, DiskLabel);
464 VOID CCABManager::OnAdd(PCFFILE File,
467 * FUNCTION: Called just before adding a file to a cabinet
469 * File = Pointer to CFFILE for file being added
470 * FileName = Pointer to buffer with name of file (full path)
473 printf("Adding %s\n", GetFileName(FileName));
477 int main(int argc, char * argv[])
479 * FUNCTION: Main entry point
481 * argc = Number of arguments on command line
482 * argv = Pointer to list of command line arguments
487 if (CABMgr.ParseCmdline(argc, argv))