Files
reactos/reactos/tools/cabman/main.cxx
Thomas Bluemel 1c3867a641 Patch by Jonathon Wilson:
fix most of ReactOS to build with -Wall -Werror by default

svn path=/trunk/; revision=6645
2003-11-14 17:13:36 +00:00

555 lines
14 KiB
C++
Executable File

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS cabinet manager
* FILE: tools/cabman/main.cpp
* PURPOSE: Main program
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 21/03-2001 Created
* CSH 15/08-2003 Made it portable
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "cabman.h"
#ifdef DBG
unsigned long DebugTraceLevel = MIN_TRACE;
//unsigned long DebugTraceLevel = MID_TRACE;
//unsigned long DebugTraceLevel = MAX_TRACE;
#endif /* DBG */
#define CM_VERSION "0.9"
char* Pad(char* Str, char PadChar, unsigned int Length)
/*
* FUNCTION: Pads a string with a character to make a given length
* ARGUMENTS:
* Str = Pointer to string to pad
* PadChar = Character to pad with
* Length = Disired length of string
* RETURNS:
* Pointer to string
* NOTES:
* Str must be at least Length + 1 bytes
*/
{
unsigned int Len;
Len = strlen(Str);
if (Len < Length) {
memcpy(&Str[Length - Len], Str, Len + 1);
memset(Str, PadChar, Length - Len);
}
return Str;
}
char* Date2Str(char* Str, unsigned short Date)
/*
* FUNCTION: Converts a DOS style date to a string
* ARGUMENTS:
* Str = Pointer to destination string
* Date = DOS style date
* RETURNS:
* Pointer to string
*/
{
unsigned long dw;
/* Month */
Str[0] = (char)('0' + ((Date & 0x01E0) >> 5) / 10);
Str[1] = (char)('0' + ((Date & 0x01E0) >> 5) % 10);
Str[2] = '-';
/* Day */
Str[3] = (char)('0' + (Date & 0x001F) / 10);
Str[4] = (char)('0' + (Date & 0x001F) % 10);
Str[5] = '-';
/* Year */
dw = 1980 + ((Date & 0xFE00) >> 9);
Str[6] = (char)('0' + dw / 1000); dw %= 1000;
Str[7] = (char)('0' + dw / 100); dw %= 100;
Str[8] = (char)('0' + dw / 10); dw %= 10;
Str[9] = (char)('0' + dw % 10);
Str[10] = '\0';
return Str;
}
char* Time2Str(char* Str, unsigned short Time)
/*
* FUNCTION: Converts a DOS style time to a string
* ARGUMENTS:
* Str = Pointer to destination string
* Time = DOS style time
* RETURNS:
* Pointer to string
*/
{
bool PM;
unsigned long Hour;
unsigned long dw;
Hour = ((Time & 0xF800) >> 11);
PM = (Hour >= 12);
Hour %= 12;
if (Hour == 0)
Hour = 12;
if (Hour >= 10)
Str[0] = (char)('0' + Hour / 10);
else Str[0] = ' ';
Str[1] = (char)('0' + Hour % 10);
Str[2] = ':';
/* Minute */
Str[3] = (char)('0' + ((Time & 0x07E0) >> 5) / 10);
Str[4] = (char)('0' + ((Time & 0x07E0) >> 5) % 10);
Str[5] = ':';
/* Second */
dw = 2 * (Time & 0x001F);
Str[6] = (char)('0' + dw / 10);
Str[7] = (char)('0' + dw % 10);
Str[8] = PM? 'p' : 'a';
Str[9] = '\0';
return Str;
}
char* Attr2Str(char* Str, unsigned short Attr)
/*
* FUNCTION: Converts attributes to a string
* ARGUMENTS:
* Str = Pointer to destination string
* Attr = Attributes
* RETURNS:
* Pointer to string
*/
{
/* Archive */
if (Attr & CAB_ATTRIB_ARCHIVE)
Str[0] = 'A';
else
Str[0] = '-';
/* Hidden */
if (Attr & CAB_ATTRIB_HIDDEN)
Str[1] = 'H';
else
Str[1] = '-';
/* Read only */
if (Attr & CAB_ATTRIB_READONLY)
Str[2] = 'R';
else
Str[2] = '-';
/* System */
if (Attr & CAB_ATTRIB_SYSTEM)
Str[3] = 'S';
else
Str[3] = '-';
Str[4] = '\0';
return Str;
}
/* CCABManager */
CCABManager::CCABManager()
/*
* FUNCTION: Default constructor
*/
{
ProcessAll = false;
InfFileOnly = false;
Mode = CM_MODE_DISPLAY;
}
CCABManager::~CCABManager()
/*
* FUNCTION: Default destructor
*/
{
}
void CCABManager::Usage()
/*
* FUNCTION: Display usage information on screen
*/
{
printf("ReactOS Cabinet Manager - Version %s\n\n", CM_VERSION);
printf("CABMAN [/D | /E] [/A] [/L dir] cabinet [filename ...]\n");
printf("CABMAN /C dirfile [/I] [/RC file]\n");
printf("CABMAN /S cabinet filename\n");
printf(" cabinet Cabinet file.\n");
printf(" filename Name of the file to extract from the cabinet.\n");
printf(" Wild cards and multiple filenames\n");
printf(" (separated by blanks) may be used.\n\n");
printf(" dirfile Name of the directive file to use.\n");
printf(" /A Process ALL cabinets. Follows cabinet chain\n");
printf(" starting in first cabinet mentioned.\n");
printf(" /C Create cabinet.\n");
printf(" /D Display cabinet directory.\n");
printf(" /E Extract files from cabinet.\n");
printf(" /I Don't create the cabinet, only the .inf file.\n");
printf(" /L dir Location to place extracted or generated files\n");
printf(" (default is current directory).\n");
printf(" /N Don't create the .inf file, only the cabinet.\n");
printf(" /RC Specify file to put in cabinet reserved area\n");
printf(" (size must be less than 64KB).\n");
printf(" /S Create simple cabinet.\n");
}
bool CCABManager::ParseCmdline(int argc, char* argv[])
/*
* FUNCTION: Parse command line arguments
* ARGUMENTS:
* argc = Number of arguments on command line
* argv = Pointer to list of command line arguments
* RETURNS:
* true if command line arguments was successfully parsed, false if not
*/
{
int i;
bool ShowUsage;
bool FoundCabinet = false;
ShowUsage = (argc < 2);
for (i = 1; i < argc; i++) {
if (argv[i][0] == '/') {
switch (argv[i][1]) {
case 'a':
case 'A': ProcessAll = true; break;
case 'c':
case 'C': Mode = CM_MODE_CREATE; break;
case 'd':
case 'D': Mode = CM_MODE_DISPLAY; break;
case 'e':
case 'E': Mode = CM_MODE_EXTRACT; break;
case 'i':
case 'I': InfFileOnly = true; break;
case 'l':
case 'L':
if (argv[i][2] == 0) {
i++;
SetDestinationPath((char*)&argv[i][0]);
} else {
SetDestinationPath((char*)&argv[i][1]);
}
break;
case 'n':
case 'N': DontGenerateInf = true; break;
case 'R':
switch (argv[i][2]) {
case 'C': /* File to put in cabinet reserved area */
if (argv[i][3] == 0) {
i++;
if (!SetCabinetReservedFile((char*)&argv[i][0])) {
printf("Cannot open cabinet reserved area file.\n");
return false;
}
} else {
if (!SetCabinetReservedFile((char*)&argv[i][3])) {
printf("Cannot open cabinet reserved area file.\n");
return false;
}
}
break;
default:
printf("Bad parameter %s.\n", argv[i]);
return false;
}
break;
case 's':
case 'S': Mode = CM_MODE_CREATE_SIMPLE; break;
default:
printf("Bad parameter %s.\n", argv[i]);
return false;
}
} else {
if ((FoundCabinet) || (Mode == CM_MODE_CREATE)) {
/* FIXME: There may be many of these if Mode != CM_MODE_CREATE */
strcpy((char*)FileName, argv[i]);
} else {
SetCabinetName(argv[i]);
FoundCabinet = true;
}
}
}
if (ShowUsage) {
Usage();
return false;
}
/* FIXME */
SelectCodec(CAB_CODEC_MSZIP);
return true;
}
bool CCABManager::CreateCabinet()
/*
* FUNCTION: Create cabinet
*/
{
unsigned long Status;
Status = Load((char*)&FileName);
if (Status != CAB_STATUS_SUCCESS) {
printf("Specified directive file could not be found: %s.\n", (char*)&FileName);
return false;
}
Parse();
return true;
}
bool CCABManager::CreateSimpleCabinet()
/*
* FUNCTION: Create cabinet
*/
{
unsigned long Status;
Status = NewCabinet();
if (Status != CAB_STATUS_SUCCESS) {
DPRINT(MIN_TRACE, ("Cannot create cabinet (%d).\n", (unsigned int)Status));
return false;
}
Status = AddFile(FileName);
if (Status != CAB_STATUS_SUCCESS) {
DPRINT(MIN_TRACE, ("Cannot add file to cabinet (%d).\n", (unsigned int)Status));
return false;
}
Status = WriteDisk(false);
if (Status == CAB_STATUS_SUCCESS)
Status = CloseDisk();
if (Status != CAB_STATUS_SUCCESS) {
DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (unsigned int)Status));
return false;
}
CloseCabinet();
return true;
}
bool CCABManager::DisplayCabinet()
/*
* FUNCTION: Display cabinet contents
*/
{
CAB_SEARCH Search;
char Str[20];
unsigned long FileCount = 0;
unsigned long ByteCount = 0;
if (Open() == CAB_STATUS_SUCCESS) {
printf("Cabinet %s\n\n", GetCabinetName());
if (FindFirst("", &Search) == CAB_STATUS_SUCCESS) {
do {
if (Search.File->FileControlID != CAB_FILE_CONTINUED) {
printf("%s ", Date2Str((char*)&Str, Search.File->FileDate));
printf("%s ", Time2Str((char*)&Str, Search.File->FileTime));
printf("%s ", Attr2Str((char*)&Str, Search.File->Attributes));
sprintf(Str, "%lu", Search.File->FileSize);
printf("%s ", Pad(Str, ' ', 13));
printf("%s\n", Search.FileName);
FileCount++;
ByteCount += Search.File->FileSize;
}
} while (FindNext(&Search) == CAB_STATUS_SUCCESS);
}
if (FileCount > 0) {
if (FileCount == 1)
printf(" 1 file ");
else {
sprintf(Str, "%lu", FileCount);
printf(" %s files ", Pad(Str, ' ', 12));
}
if (ByteCount == 1)
printf(" 1 byte\n");
else {
sprintf(Str, "%lu", ByteCount);
printf("%s bytes\n", Pad(Str, ' ', 12));
}
} else {
/* There should be at least one file in a cabinet */
printf("No files in cabinet.");
}
return true;
} else
printf("Cannot not open file: %s\n", GetCabinetName());
return false;
}
bool CCABManager::ExtractFromCabinet()
/*
* FUNCTION: Extract file(s) from cabinet
*/
{
CAB_SEARCH Search;
unsigned long Status;
if (Open() == CAB_STATUS_SUCCESS) {
printf("Cabinet %s\n\n", GetCabinetName());
if (FindFirst("", &Search) == CAB_STATUS_SUCCESS) {
do {
switch (Status = ExtractFile(Search.FileName)) {
case CAB_STATUS_SUCCESS:
break;
case CAB_STATUS_INVALID_CAB:
printf("Cabinet contains errors.\n");
return false;
case CAB_STATUS_UNSUPPCOMP:
printf("Cabinet uses unsupported compression type.\n");
return false;
case CAB_STATUS_CANNOT_WRITE:
printf("You've run out of free space on the destination volume or the volume is damaged.\n");
return false;
default:
printf("Unspecified error code (%d).\n", (unsigned int)Status);
return false;
}
} while (FindNext(&Search) == CAB_STATUS_SUCCESS);
}
return true;
} else
printf("Cannot not open file: %s.\n", GetCabinetName());
return false;
}
bool CCABManager::Run()
/*
* FUNCTION: Process cabinet
*/
{
printf("ReactOS Cabinet Manager - Version %s\n\n", CM_VERSION);
switch (Mode) {
case CM_MODE_CREATE: return CreateCabinet(); break;
case CM_MODE_DISPLAY: return DisplayCabinet(); break;
case CM_MODE_EXTRACT: return ExtractFromCabinet(); break;
case CM_MODE_CREATE_SIMPLE: return CreateSimpleCabinet(); break;
default:
break;
}
return false;
}
/* Event handlers */
bool CCABManager::OnOverwrite(PCFFILE File,
char* FileName)
/*
* FUNCTION: Called when extracting a file and it already exists
* ARGUMENTS:
* File = Pointer to CFFILE for file being extracted
* Filename = Pointer to buffer with name of file (full path)
* RETURNS
* true if the file should be overwritten, false if not
*/
{
if (Mode == CM_MODE_CREATE)
return true;
/* Always overwrite */
return true;
}
void CCABManager::OnExtract(PCFFILE File,
char* FileName)
/*
* FUNCTION: Called just before extracting a file
* ARGUMENTS:
* File = Pointer to CFFILE for file being extracted
* FileName = Pointer to buffer with name of file (full path)
*/
{
printf("Extracting %s\n", GetFileName(FileName));
}
void CCABManager::OnDiskChange(char* CabinetName,
char* DiskLabel)
/*
* FUNCTION: Called when a new disk is to be processed
* ARGUMENTS:
* CabinetName = Pointer to buffer with name of cabinet
* DiskLabel = Pointer to buffer with label of disk
*/
{
printf("\nChanging to cabinet %s - %s\n\n", CabinetName, DiskLabel);
}
void CCABManager::OnAdd(PCFFILE File,
char* FileName)
/*
* FUNCTION: Called just before adding a file to a cabinet
* ARGUMENTS:
* File = Pointer to CFFILE for file being added
* FileName = Pointer to buffer with name of file (full path)
*/
{
printf("Adding %s\n", GetFileName(FileName));
}
int main(int argc, char * argv[])
/*
* FUNCTION: Main entry point
* ARGUMENTS:
* argc = Number of arguments on command line
* argv = Pointer to list of command line arguments
*/
{
CCABManager CABMgr;
bool status = false;
if (CABMgr.ParseCmdline(argc, argv)) {
status = CABMgr.Run();
}
if (status) {
return 0;
} else {
return 1;
}
}
/* EOF */