Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmain.cxx
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS cabinet manager 00004 * FILE: tools/cabman/main.cpp 00005 * PURPOSE: Main program 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * Colin Finck <mail@colinfinck.de> 00008 * REVISIONS: 00009 * CSH 21/03-2001 Created 00010 * CSH 15/08-2003 Made it portable 00011 * CF 04/05-2007 Made it compatible with 64-bit operating systems 00012 */ 00013 #include <stdlib.h> 00014 #include <stdarg.h> 00015 #include <string.h> 00016 #include <stdio.h> 00017 #include "cabman.h" 00018 00019 00020 #if DBG 00021 00022 ULONG DebugTraceLevel = MIN_TRACE; 00023 //ULONG DebugTraceLevel = MID_TRACE; 00024 //ULONG DebugTraceLevel = MAX_TRACE; 00025 00026 #endif /* DBG */ 00027 00028 00029 char* Pad(char* Str, char PadChar, ULONG Length) 00030 /* 00031 * FUNCTION: Pads a string with a character to make a given length 00032 * ARGUMENTS: 00033 * Str = Pointer to string to pad 00034 * PadChar = Character to pad with 00035 * Length = Disired length of string 00036 * RETURNS: 00037 * Pointer to string 00038 * NOTES: 00039 * Str must be at least Length + 1 bytes 00040 */ 00041 { 00042 ULONG Len; 00043 00044 Len = (ULONG)strlen(Str); 00045 00046 if (Len < Length) 00047 { 00048 memcpy(&Str[Length - Len], Str, Len + 1); 00049 memset(Str, PadChar, Length - Len); 00050 } 00051 return Str; 00052 } 00053 00054 00055 char* Date2Str(char* Str, USHORT Date) 00056 /* 00057 * FUNCTION: Converts a DOS style date to a string 00058 * ARGUMENTS: 00059 * Str = Pointer to destination string 00060 * Date = DOS style date 00061 * RETURNS: 00062 * Pointer to string 00063 */ 00064 { 00065 ULONG dw; 00066 00067 /* Month */ 00068 Str[0] = (char)('0' + ((Date & 0x01E0) >> 5) / 10); 00069 Str[1] = (char)('0' + ((Date & 0x01E0) >> 5) % 10); 00070 Str[2] = '-'; 00071 /* Day */ 00072 Str[3] = (char)('0' + (Date & 0x001F) / 10); 00073 Str[4] = (char)('0' + (Date & 0x001F) % 10); 00074 Str[5] = '-'; 00075 /* Year */ 00076 dw = 1980 + ((Date & 0xFE00) >> 9); 00077 Str[6] = (char)('0' + dw / 1000); dw %= 1000; 00078 Str[7] = (char)('0' + dw / 100); dw %= 100; 00079 Str[8] = (char)('0' + dw / 10); dw %= 10; 00080 Str[9] = (char)('0' + dw % 10); 00081 Str[10] = '\0'; 00082 return Str; 00083 } 00084 00085 00086 char* Time2Str(char* Str, USHORT Time) 00087 /* 00088 * FUNCTION: Converts a DOS style time to a string 00089 * ARGUMENTS: 00090 * Str = Pointer to destination string 00091 * Time = DOS style time 00092 * RETURNS: 00093 * Pointer to string 00094 */ 00095 { 00096 bool PM; 00097 ULONG Hour; 00098 ULONG dw; 00099 00100 Hour = ((Time & 0xF800) >> 11); 00101 PM = (Hour >= 12); 00102 Hour %= 12; 00103 if (Hour == 0) 00104 Hour = 12; 00105 00106 if (Hour >= 10) 00107 Str[0] = (char)('0' + Hour / 10); 00108 else Str[0] = ' '; 00109 Str[1] = (char)('0' + Hour % 10); 00110 Str[2] = ':'; 00111 /* Minute */ 00112 Str[3] = (char)('0' + ((Time & 0x07E0) >> 5) / 10); 00113 Str[4] = (char)('0' + ((Time & 0x07E0) >> 5) % 10); 00114 Str[5] = ':'; 00115 /* Second */ 00116 dw = 2 * (Time & 0x001F); 00117 Str[6] = (char)('0' + dw / 10); 00118 Str[7] = (char)('0' + dw % 10); 00119 00120 Str[8] = PM? 'p' : 'a'; 00121 Str[9] = '\0'; 00122 return Str; 00123 } 00124 00125 00126 char* Attr2Str(char* Str, USHORT Attr) 00127 /* 00128 * FUNCTION: Converts attributes to a string 00129 * ARGUMENTS: 00130 * Str = Pointer to destination string 00131 * Attr = Attributes 00132 * RETURNS: 00133 * Pointer to string 00134 */ 00135 { 00136 /* Archive */ 00137 if (Attr & CAB_ATTRIB_ARCHIVE) 00138 Str[0] = 'A'; 00139 else 00140 Str[0] = '-'; 00141 00142 /* Hidden */ 00143 if (Attr & CAB_ATTRIB_HIDDEN) 00144 Str[1] = 'H'; 00145 else 00146 Str[1] = '-'; 00147 00148 /* Read only */ 00149 if (Attr & CAB_ATTRIB_READONLY) 00150 Str[2] = 'R'; 00151 else 00152 Str[2] = '-'; 00153 00154 /* System */ 00155 if (Attr & CAB_ATTRIB_SYSTEM) 00156 Str[3] = 'S'; 00157 else 00158 Str[3] = '-'; 00159 00160 Str[4] = '\0'; 00161 return Str; 00162 } 00163 00164 00165 /* CCABManager */ 00166 00167 CCABManager::CCABManager() 00168 /* 00169 * FUNCTION: Default constructor 00170 */ 00171 { 00172 ProcessAll = false; 00173 InfFileOnly = false; 00174 Mode = CM_MODE_DISPLAY; 00175 FileName[0] = 0; 00176 } 00177 00178 00179 CCABManager::~CCABManager() 00180 /* 00181 * FUNCTION: Default destructor 00182 */ 00183 { 00184 } 00185 00186 00187 void CCABManager::Usage() 00188 /* 00189 * FUNCTION: Display usage information on screen 00190 */ 00191 { 00192 printf("ReactOS Cabinet Manager\n\n"); 00193 printf("CABMAN [-D | -E] [-A] [-L dir] cabinet [filename ...]\n"); 00194 printf("CABMAN [-M mode] -C dirfile [-I] [-RC file] [-P dir]\n"); 00195 printf("CABMAN [-M mode] -S cabinet filename [...]\n"); 00196 printf(" cabinet Cabinet file.\n"); 00197 printf(" filename Name of the file to add to or extract from the cabinet.\n"); 00198 printf(" Wild cards and multiple filenames\n"); 00199 printf(" (separated by blanks) may be used.\n\n"); 00200 00201 printf(" dirfile Name of the directive file to use.\n"); 00202 00203 printf(" -A Process ALL cabinets. Follows cabinet chain\n"); 00204 printf(" starting in first cabinet mentioned.\n"); 00205 printf(" -C Create cabinet.\n"); 00206 printf(" -D Display cabinet directory.\n"); 00207 printf(" -E Extract files from cabinet.\n"); 00208 printf(" -I Don't create the cabinet, only the .inf file.\n"); 00209 printf(" -L dir Location to place extracted or generated files\n"); 00210 printf(" (default is current directory).\n"); 00211 printf(" -M mode Specify the compression method to use:\n"); 00212 printf(" raw - No compression\n"); 00213 printf(" mszip - MsZip compression (default)\n"); 00214 printf(" -N Don't create the .inf file, only the cabinet.\n"); 00215 printf(" -RC Specify file to put in cabinet reserved area\n"); 00216 printf(" (size must be less than 64KB).\n"); 00217 printf(" -S Create simple cabinet.\n"); 00218 printf(" -P dir Files in the .dff are relative to this directory\n"); 00219 } 00220 00221 bool CCABManager::ParseCmdline(int argc, char* argv[]) 00222 /* 00223 * FUNCTION: Parse command line arguments 00224 * ARGUMENTS: 00225 * argc = Number of arguments on command line 00226 * argv = Pointer to list of command line arguments 00227 * RETURNS: 00228 * true if command line arguments was successfully parsed, false if not 00229 */ 00230 { 00231 int i; 00232 bool ShowUsage; 00233 bool FoundCabinet = false; 00234 00235 ShowUsage = (argc < 2); 00236 00237 for (i = 1; i < argc; i++) 00238 { 00239 if (argv[i][0] == '-') 00240 { 00241 switch (argv[i][1]) 00242 { 00243 case 'a': 00244 case 'A': 00245 ProcessAll = true; 00246 break; 00247 00248 case 'c': 00249 case 'C': 00250 Mode = CM_MODE_CREATE; 00251 break; 00252 00253 case 'd': 00254 case 'D': 00255 Mode = CM_MODE_DISPLAY; 00256 break; 00257 00258 case 'e': 00259 case 'E': 00260 Mode = CM_MODE_EXTRACT; 00261 break; 00262 00263 case 'i': 00264 case 'I': 00265 InfFileOnly = true; 00266 break; 00267 00268 case 'l': 00269 case 'L': 00270 if (argv[i][2] == 0) 00271 { 00272 i++; 00273 SetDestinationPath(&argv[i][0]); 00274 } 00275 else 00276 SetDestinationPath(&argv[i][2]); 00277 00278 break; 00279 00280 case 'm': 00281 case 'M': 00282 // Set the compression codec (only affects compression, not decompression) 00283 if(argv[i][2] == 0) 00284 { 00285 i++; 00286 00287 if( !SetCompressionCodec(&argv[i][0]) ) 00288 return false; 00289 } 00290 else 00291 { 00292 if( !SetCompressionCodec(&argv[i][2]) ) 00293 return false; 00294 } 00295 00296 break; 00297 00298 case 'n': 00299 case 'N': 00300 DontGenerateInf = true; 00301 break; 00302 00303 case 'R': 00304 switch (argv[i][2]) 00305 { 00306 case 'C': /* File to put in cabinet reserved area */ 00307 if (argv[i][3] == 0) 00308 { 00309 i++; 00310 if (!SetCabinetReservedFile(&argv[i][0])) 00311 { 00312 printf("Cannot open cabinet reserved area file.\n"); 00313 return false; 00314 } 00315 } 00316 else 00317 { 00318 if (!SetCabinetReservedFile(&argv[i][3])) 00319 { 00320 printf("Cannot open cabinet reserved area file.\n"); 00321 return false; 00322 } 00323 } 00324 break; 00325 00326 default: 00327 printf("Bad parameter %s.\n", argv[i]); 00328 return false; 00329 } 00330 break; 00331 00332 case 's': 00333 case 'S': 00334 Mode = CM_MODE_CREATE_SIMPLE; 00335 break; 00336 00337 case 'P': 00338 if (argv[i][2] == 0) 00339 { 00340 i++; 00341 SetFileRelativePath(&argv[i][0]); 00342 } 00343 else 00344 SetFileRelativePath(&argv[i][2]); 00345 00346 break; 00347 00348 default: 00349 printf("Bad parameter %s.\n", argv[i]); 00350 return false; 00351 } 00352 } 00353 else 00354 { 00355 if(Mode == CM_MODE_CREATE) 00356 { 00357 if(FileName[0]) 00358 { 00359 printf("You may only specify one directive file!\n"); 00360 return false; 00361 } 00362 else 00363 { 00364 // For creating cabinets, this argument is the path to the directive file 00365 strcpy(FileName, argv[i]); 00366 } 00367 } 00368 else if(FoundCabinet) 00369 { 00370 // For creating simple cabinets, displaying or extracting them, add the argument as a search criteria 00371 AddSearchCriteria(argv[i]); 00372 } 00373 else 00374 { 00375 SetCabinetName(argv[i]); 00376 FoundCabinet = true; 00377 } 00378 } 00379 } 00380 00381 if (ShowUsage) 00382 { 00383 Usage(); 00384 return false; 00385 } 00386 00387 // Select MsZip by default for creating cabinets 00388 if( (Mode == CM_MODE_CREATE || Mode == CM_MODE_CREATE_SIMPLE) && !IsCodecSelected() ) 00389 SelectCodec(CAB_CODEC_MSZIP); 00390 00391 // Search criteria (= the filename argument) is necessary for creating a simple cabinet 00392 if( Mode == CM_MODE_CREATE_SIMPLE && !HasSearchCriteria()) 00393 { 00394 printf("You have to enter input file names!\n"); 00395 return false; 00396 } 00397 00398 return true; 00399 } 00400 00401 00402 bool CCABManager::CreateCabinet() 00403 /* 00404 * FUNCTION: Create cabinet 00405 */ 00406 { 00407 ULONG Status; 00408 00409 Status = Load(FileName); 00410 if (Status != CAB_STATUS_SUCCESS) 00411 { 00412 printf("Specified directive file could not be found: %s.\n", FileName); 00413 return false; 00414 } 00415 00416 Status = Parse(); 00417 00418 return (Status == CAB_STATUS_SUCCESS ? true : false); 00419 } 00420 00421 bool CCABManager::DisplayCabinet() 00422 /* 00423 * FUNCTION: Display cabinet contents 00424 */ 00425 { 00426 CAB_SEARCH Search; 00427 char Str[20]; 00428 ULONG FileCount = 0; 00429 ULONG ByteCount = 0; 00430 00431 if (Open() == CAB_STATUS_SUCCESS) 00432 { 00433 printf("Cabinet %s\n\n", GetCabinetName()); 00434 00435 if (FindFirst(&Search) == CAB_STATUS_SUCCESS) 00436 { 00437 do 00438 { 00439 if (Search.File->FileControlID != CAB_FILE_CONTINUED) 00440 { 00441 printf("%s ", Date2Str(Str, Search.File->FileDate)); 00442 printf("%s ", Time2Str(Str, Search.File->FileTime)); 00443 printf("%s ", Attr2Str(Str, Search.File->Attributes)); 00444 sprintf(Str, "%u", (UINT)Search.File->FileSize); 00445 printf("%s ", Pad(Str, ' ', 13)); 00446 printf("%s\n", Search.FileName); 00447 00448 FileCount++; 00449 ByteCount += Search.File->FileSize; 00450 } 00451 } while (FindNext(&Search) == CAB_STATUS_SUCCESS); 00452 } 00453 00454 DestroySearchCriteria(); 00455 00456 if (FileCount > 0) { 00457 if (FileCount == 1) 00458 printf(" 1 file "); 00459 else 00460 { 00461 sprintf(Str, "%u", (UINT)FileCount); 00462 printf(" %s files ", Pad(Str, ' ', 12)); 00463 } 00464 00465 if (ByteCount == 1) 00466 printf(" 1 byte\n"); 00467 else 00468 { 00469 sprintf(Str, "%u", (UINT)ByteCount); 00470 printf("%s bytes\n", Pad(Str, ' ', 12)); 00471 } 00472 } 00473 else 00474 { 00475 /* There should be at least one file in a cabinet */ 00476 printf("No files in cabinet."); 00477 } 00478 return true; 00479 } 00480 else 00481 printf("Cannot open file: %s\n", GetCabinetName()); 00482 00483 return false; 00484 } 00485 00486 00487 bool CCABManager::ExtractFromCabinet() 00488 /* 00489 * FUNCTION: Extract file(s) from cabinet 00490 */ 00491 { 00492 bool bRet = true; 00493 CAB_SEARCH Search; 00494 ULONG Status; 00495 00496 if (Open() == CAB_STATUS_SUCCESS) 00497 { 00498 printf("Cabinet %s\n\n", GetCabinetName()); 00499 00500 if (FindFirst(&Search) == CAB_STATUS_SUCCESS) 00501 { 00502 do 00503 { 00504 switch (Status = ExtractFile(Search.FileName)) 00505 { 00506 case CAB_STATUS_SUCCESS: 00507 break; 00508 00509 case CAB_STATUS_INVALID_CAB: 00510 printf("Cabinet contains errors.\n"); 00511 bRet = false; 00512 break; 00513 00514 case CAB_STATUS_UNSUPPCOMP: 00515 printf("Cabinet uses unsupported compression type.\n"); 00516 bRet = false; 00517 break; 00518 00519 case CAB_STATUS_CANNOT_WRITE: 00520 printf("You've run out of free space on the destination volume or the volume is damaged.\n"); 00521 bRet = false; 00522 break; 00523 00524 default: 00525 printf("Unspecified error code (%u).\n", (UINT)Status); 00526 bRet = false; 00527 break; 00528 } 00529 00530 if(!bRet) 00531 break; 00532 } while (FindNext(&Search) == CAB_STATUS_SUCCESS); 00533 00534 DestroySearchCriteria(); 00535 } 00536 00537 return bRet; 00538 } 00539 else 00540 printf("Cannot open file: %s.\n", GetCabinetName()); 00541 00542 return false; 00543 } 00544 00545 00546 bool CCABManager::Run() 00547 /* 00548 * FUNCTION: Process cabinet 00549 */ 00550 { 00551 printf("ReactOS Cabinet Manager\n\n"); 00552 00553 switch (Mode) 00554 { 00555 case CM_MODE_CREATE: 00556 return CreateCabinet(); 00557 00558 case CM_MODE_DISPLAY: 00559 return DisplayCabinet(); 00560 00561 case CM_MODE_EXTRACT: 00562 return ExtractFromCabinet(); 00563 00564 case CM_MODE_CREATE_SIMPLE: 00565 return CreateSimpleCabinet(); 00566 00567 default: 00568 break; 00569 } 00570 return false; 00571 } 00572 00573 00574 /* Event handlers */ 00575 00576 bool CCABManager::OnOverwrite(PCFFILE File, 00577 char* FileName) 00578 /* 00579 * FUNCTION: Called when extracting a file and it already exists 00580 * ARGUMENTS: 00581 * File = Pointer to CFFILE for file being extracted 00582 * Filename = Pointer to buffer with name of file (full path) 00583 * RETURNS 00584 * true if the file should be overwritten, false if not 00585 */ 00586 { 00587 if (Mode == CM_MODE_CREATE) 00588 return true; 00589 00590 /* Always overwrite */ 00591 return true; 00592 } 00593 00594 00595 void CCABManager::OnExtract(PCFFILE File, 00596 char* FileName) 00597 /* 00598 * FUNCTION: Called just before extracting a file 00599 * ARGUMENTS: 00600 * File = Pointer to CFFILE for file being extracted 00601 * FileName = Pointer to buffer with name of file (full path) 00602 */ 00603 { 00604 printf("Extracting %s\n", GetFileName(FileName)); 00605 } 00606 00607 00608 00609 void CCABManager::OnDiskChange(char* CabinetName, 00610 char* DiskLabel) 00611 /* 00612 * FUNCTION: Called when a new disk is to be processed 00613 * ARGUMENTS: 00614 * CabinetName = Pointer to buffer with name of cabinet 00615 * DiskLabel = Pointer to buffer with label of disk 00616 */ 00617 { 00618 printf("\nChanging to cabinet %s - %s\n\n", CabinetName, DiskLabel); 00619 } 00620 00621 00622 void CCABManager::OnAdd(PCFFILE File, 00623 char* FileName) 00624 /* 00625 * FUNCTION: Called just before adding a file to a cabinet 00626 * ARGUMENTS: 00627 * File = Pointer to CFFILE for file being added 00628 * FileName = Pointer to buffer with name of file (full path) 00629 */ 00630 { 00631 printf("Adding %s\n", GetFileName(FileName)); 00632 } 00633 00634 00635 int main(int argc, char * argv[]) 00636 /* 00637 * FUNCTION: Main entry point 00638 * ARGUMENTS: 00639 * argc = Number of arguments on command line 00640 * argv = Pointer to list of command line arguments 00641 */ 00642 { 00643 CCABManager CABMgr; 00644 bool status = false; 00645 00646 if (CABMgr.ParseCmdline(argc, argv)) 00647 status = CABMgr.Run(); 00648 00649 return (status ? 0 : 1); 00650 } 00651 00652 /* EOF */ Generated on Sat May 26 2012 04:36:34 for ReactOS by
1.7.6.1
|