/* * 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 #include #include #include #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, "%d", 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, "%d", FileCount); printf(" %s files ", Pad(Str, ' ', 12)); } if (ByteCount == 1) printf(" 1 byte\n"); else { sprintf(Str, "%d", 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 */ { char ch; 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 */