ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

main.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.