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
, PCHAR 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
))