ReactOS  0.4.12-dev-375-g61fed54
main.cxx
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS cabinet manager
4  * FILE: tools/cabman/main.cxx
5  * PURPOSE: Main program
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * Colin Finck <mail@colinfinck.de>
8  * REVISIONS:
9  * CSH 21/03-2001 Created
10  * CSH 15/08-2003 Made it portable
11  * CF 04/05-2007 Made it compatible with 64-bit operating systems
12  */
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include "cabman.h"
18 
19 
20 #if DBG
21 
23 //ULONG DebugTraceLevel = MID_TRACE;
24 //ULONG DebugTraceLevel = MAX_TRACE;
25 
26 #endif /* DBG */
27 
28 
29 char* Pad(char* Str, char PadChar, ULONG Length)
30 /*
31  * FUNCTION: Pads a string with a character to make a given length
32  * ARGUMENTS:
33  * Str = Pointer to string to pad
34  * PadChar = Character to pad with
35  * Length = Disired length of string
36  * RETURNS:
37  * Pointer to string
38  * NOTES:
39  * Str must be at least Length + 1 bytes
40  */
41 {
42  ULONG Len;
43 
44  Len = (ULONG)strlen(Str);
45 
46  if (Len < Length)
47  {
48  memcpy(&Str[Length - Len], Str, Len + 1);
49  memset(Str, PadChar, Length - Len);
50  }
51  return Str;
52 }
53 
54 
55 char* Date2Str(char* Str, USHORT Date)
56 /*
57  * FUNCTION: Converts a DOS style date to a string
58  * ARGUMENTS:
59  * Str = Pointer to destination string
60  * Date = DOS style date
61  * RETURNS:
62  * Pointer to string
63  */
64 {
65  ULONG dw;
66 
67  /* Month */
68  Str[0] = (char)('0' + ((Date & 0x01E0) >> 5) / 10);
69  Str[1] = (char)('0' + ((Date & 0x01E0) >> 5) % 10);
70  Str[2] = '-';
71  /* Day */
72  Str[3] = (char)('0' + (Date & 0x001F) / 10);
73  Str[4] = (char)('0' + (Date & 0x001F) % 10);
74  Str[5] = '-';
75  /* Year */
76  dw = 1980 + ((Date & 0xFE00) >> 9);
77  Str[6] = (char)('0' + dw / 1000); dw %= 1000;
78  Str[7] = (char)('0' + dw / 100); dw %= 100;
79  Str[8] = (char)('0' + dw / 10); dw %= 10;
80  Str[9] = (char)('0' + dw % 10);
81  Str[10] = '\0';
82  return Str;
83 }
84 
85 
86 char* Time2Str(char* Str, USHORT Time)
87 /*
88  * FUNCTION: Converts a DOS style time to a string
89  * ARGUMENTS:
90  * Str = Pointer to destination string
91  * Time = DOS style time
92  * RETURNS:
93  * Pointer to string
94  */
95 {
96  bool PM;
97  ULONG Hour;
98  ULONG dw;
99 
100  Hour = ((Time & 0xF800) >> 11);
101  PM = (Hour >= 12);
102  Hour %= 12;
103  if (Hour == 0)
104  Hour = 12;
105 
106  if (Hour >= 10)
107  Str[0] = (char)('0' + Hour / 10);
108  else Str[0] = ' ';
109  Str[1] = (char)('0' + Hour % 10);
110  Str[2] = ':';
111  /* Minute */
112  Str[3] = (char)('0' + ((Time & 0x07E0) >> 5) / 10);
113  Str[4] = (char)('0' + ((Time & 0x07E0) >> 5) % 10);
114  Str[5] = ':';
115  /* Second */
116  dw = 2 * (Time & 0x001F);
117  Str[6] = (char)('0' + dw / 10);
118  Str[7] = (char)('0' + dw % 10);
119 
120  Str[8] = PM? 'p' : 'a';
121  Str[9] = '\0';
122  return Str;
123 }
124 
125 
126 char* Attr2Str(char* Str, USHORT Attr)
127 /*
128  * FUNCTION: Converts attributes to a string
129  * ARGUMENTS:
130  * Str = Pointer to destination string
131  * Attr = Attributes
132  * RETURNS:
133  * Pointer to string
134  */
135 {
136  /* Archive */
137  if (Attr & CAB_ATTRIB_ARCHIVE)
138  Str[0] = 'A';
139  else
140  Str[0] = '-';
141 
142  /* Hidden */
143  if (Attr & CAB_ATTRIB_HIDDEN)
144  Str[1] = 'H';
145  else
146  Str[1] = '-';
147 
148  /* Read only */
149  if (Attr & CAB_ATTRIB_READONLY)
150  Str[2] = 'R';
151  else
152  Str[2] = '-';
153 
154  /* System */
155  if (Attr & CAB_ATTRIB_SYSTEM)
156  Str[3] = 'S';
157  else
158  Str[3] = '-';
159 
160  Str[4] = '\0';
161  return Str;
162 }
163 
164 
165 /* CCABManager */
166 
168 /*
169  * FUNCTION: Default constructor
170  */
171 {
172  ProcessAll = false;
173  InfFileOnly = false;
175  FileName[0] = 0;
176  Verbose = false;
177 }
178 
179 
181 /*
182  * FUNCTION: Default destructor
183  */
184 {
185 }
186 
187 
189 /*
190  * FUNCTION: Display usage information on screen
191  */
192 {
193  printf("ReactOS Cabinet Manager\n\n");
194  printf("CABMAN [-D | -E] [-A] [-L dir] cabinet [filename ...]\n");
195  printf("CABMAN [-M mode] -C dirfile [-I] [-RC file] [-P dir]\n");
196  printf("CABMAN [-M mode] -S cabinet filename [...]\n");
197  printf(" cabinet Cabinet file.\n");
198  printf(" filename Name of the file to add to or extract from the cabinet.\n");
199  printf(" Wild cards and multiple filenames\n");
200  printf(" (separated by blanks) may be used.\n\n");
201 
202  printf(" dirfile Name of the directive file to use.\n");
203 
204  printf(" -A Process ALL cabinets. Follows cabinet chain\n");
205  printf(" starting in first cabinet mentioned.\n");
206  printf(" -C Create cabinet.\n");
207  printf(" -D Display cabinet directory.\n");
208  printf(" -E Extract files from cabinet.\n");
209  printf(" -I Don't create the cabinet, only the .inf file.\n");
210  printf(" -L dir Location to place extracted or generated files\n");
211  printf(" (default is current directory).\n");
212  printf(" -M mode Specify the compression method to use:\n");
213  printf(" raw - No compression\n");
214  printf(" mszip - MsZip compression (default)\n");
215  printf(" -N Don't create the .inf file, only the cabinet.\n");
216  printf(" -RC Specify file to put in cabinet reserved area\n");
217  printf(" (size must be less than 64KB).\n");
218  printf(" -S Create simple cabinet.\n");
219  printf(" -P dir Files in the .dff are relative to this directory.\n");
220  printf(" -V Verbose mode (prints more messages).\n");
221 }
222 
224 /*
225  * FUNCTION: Parse command line arguments
226  * ARGUMENTS:
227  * argc = Number of arguments on command line
228  * argv = Pointer to list of command line arguments
229  * RETURNS:
230  * true if command line arguments was successfully parsed, false if not
231  */
232 {
233  int i;
234  bool ShowUsage;
235  bool FoundCabinet = false;
236 
237  ShowUsage = (argc < 2);
238 
239  for (i = 1; i < argc; i++)
240  {
241  if (argv[i][0] == '-')
242  {
243  switch (argv[i][1])
244  {
245  case 'a':
246  case 'A':
247  ProcessAll = true;
248  break;
249 
250  case 'c':
251  case 'C':
253  break;
254 
255  case 'd':
256  case 'D':
258  break;
259 
260  case 'e':
261  case 'E':
263  break;
264 
265  case 'i':
266  case 'I':
267  InfFileOnly = true;
268  break;
269 
270  case 'l':
271  case 'L':
272  if (argv[i][2] == 0)
273  {
274  i++;
275  SetDestinationPath(&argv[i][0]);
276  }
277  else
278  SetDestinationPath(&argv[i][2]);
279 
280  break;
281 
282  case 'm':
283  case 'M':
284  // Set the compression codec (only affects compression, not decompression)
285  if(argv[i][2] == 0)
286  {
287  i++;
288 
289  if( !SetCompressionCodec(&argv[i][0]) )
290  return false;
291  }
292  else
293  {
294  if( !SetCompressionCodec(&argv[i][2]) )
295  return false;
296  }
297 
298  break;
299 
300  case 'n':
301  case 'N':
302  DontGenerateInf = true;
303  break;
304 
305  case 'R':
306  switch (argv[i][2])
307  {
308  case 'C': /* File to put in cabinet reserved area */
309  if (argv[i][3] == 0)
310  {
311  i++;
312  if (!SetCabinetReservedFile(&argv[i][0]))
313  {
314  printf("ERROR: Cannot open cabinet reserved area file.\n");
315  return false;
316  }
317  }
318  else
319  {
320  if (!SetCabinetReservedFile(&argv[i][3]))
321  {
322  printf("ERROR: Cannot open cabinet reserved area file.\n");
323  return false;
324  }
325  }
326  break;
327 
328  default:
329  printf("ERROR: Bad parameter %s.\n", argv[i]);
330  return false;
331  }
332  break;
333 
334  case 's':
335  case 'S':
337  break;
338 
339  case 'P':
340  if (argv[i][2] == 0)
341  {
342  i++;
343  SetFileRelativePath(&argv[i][0]);
344  }
345  else
346  SetFileRelativePath(&argv[i][2]);
347 
348  break;
349 
350  case 'V':
351  Verbose = true;
352  break;
353 
354  default:
355  printf("ERROR: Bad parameter %s.\n", argv[i]);
356  return false;
357  }
358  }
359  else
360  {
361  if(Mode == CM_MODE_CREATE)
362  {
363  if(FileName[0])
364  {
365  printf("ERROR: You may only specify one directive file!\n");
366  return false;
367  }
368  else
369  {
370  // For creating cabinets, this argument is the path to the directive file
371  strcpy(FileName, argv[i]);
372  }
373  }
374  else if(FoundCabinet)
375  {
376  // For creating simple cabinets, displaying or extracting them, add the argument as a search criteria
378  }
379  else
380  {
382  FoundCabinet = true;
383  }
384  }
385  }
386 
387  if (ShowUsage)
388  {
389  Usage();
390  return false;
391  }
392 
393  // Select MsZip by default for creating cabinets
396 
397  // Search criteria (= the filename argument) is necessary for creating a simple cabinet
399  {
400  printf("ERROR: You have to enter input file names!\n");
401  return false;
402  }
403 
404  return true;
405 }
406 
407 
409 /*
410  * FUNCTION: Create cabinet
411  */
412 {
413  ULONG Status;
414 
415  Status = Load(FileName);
416  if (Status != CAB_STATUS_SUCCESS)
417  {
418  printf("ERROR: Specified directive file could not be found: %s.\n", FileName);
419  return false;
420  }
421 
422  Status = Parse();
423 
424  return (Status == CAB_STATUS_SUCCESS ? true : false);
425 }
426 
428 /*
429  * FUNCTION: Display cabinet contents
430  */
431 {
432  CAB_SEARCH Search;
433  char Str[20];
434  ULONG FileCount = 0;
435  ULONG ByteCount = 0;
436 
437  if (Open() == CAB_STATUS_SUCCESS)
438  {
439  if (Verbose)
440  {
441  printf("Cabinet %s\n\n", GetCabinetName());
442  }
443 
444  if (FindFirst(&Search) == CAB_STATUS_SUCCESS)
445  {
446  do
447  {
448  if (Search.File->FileControlID != CAB_FILE_CONTINUED)
449  {
450  printf("%s ", Date2Str(Str, Search.File->FileDate));
451  printf("%s ", Time2Str(Str, Search.File->FileTime));
452  printf("%s ", Attr2Str(Str, Search.File->Attributes));
453  sprintf(Str, "%u", (UINT)Search.File->FileSize);
454  printf("%s ", Pad(Str, ' ', 13));
455  printf("%s\n", Search.FileName);
456 
457  FileCount++;
458  ByteCount += Search.File->FileSize;
459  }
460  } while (FindNext(&Search) == CAB_STATUS_SUCCESS);
461  }
462 
464 
465  if (FileCount > 0) {
466  if (FileCount == 1)
467  printf(" 1 file ");
468  else
469  {
470  sprintf(Str, "%u", (UINT)FileCount);
471  printf(" %s files ", Pad(Str, ' ', 12));
472  }
473 
474  if (ByteCount == 1)
475  printf(" 1 byte\n");
476  else
477  {
478  sprintf(Str, "%u", (UINT)ByteCount);
479  printf("%s bytes\n", Pad(Str, ' ', 12));
480  }
481  }
482  else
483  {
484  /* There should be at least one file in a cabinet */
485  printf("WARNING: No files in cabinet.");
486  }
487  return true;
488  }
489  else
490  printf("ERROR: Cannot open file: %s\n", GetCabinetName());
491 
492  return false;
493 }
494 
495 
497 /*
498  * FUNCTION: Extract file(s) from cabinet
499  */
500 {
501  bool bRet = true;
502  CAB_SEARCH Search;
503  ULONG Status;
504 
505  if (Open() == CAB_STATUS_SUCCESS)
506  {
507  if (Verbose)
508  {
509  printf("Cabinet %s\n\n", GetCabinetName());
510  }
511 
512  if (FindFirst(&Search) == CAB_STATUS_SUCCESS)
513  {
514  do
515  {
516  switch (Status = ExtractFile(Search.FileName))
517  {
518  case CAB_STATUS_SUCCESS:
519  break;
520 
522  printf("ERROR: Cabinet contains errors.\n");
523  bRet = false;
524  break;
525 
527  printf("ERROR: Cabinet uses unsupported compression type.\n");
528  bRet = false;
529  break;
530 
532  printf("ERROR: You've run out of free space on the destination volume or the volume is damaged.\n");
533  bRet = false;
534  break;
535 
536  default:
537  printf("ERROR: Unspecified error code (%u).\n", (UINT)Status);
538  bRet = false;
539  break;
540  }
541 
542  if(!bRet)
543  break;
544  } while (FindNext(&Search) == CAB_STATUS_SUCCESS);
545 
547  }
548 
549  return bRet;
550  }
551  else
552  printf("ERROR: Cannot open file: %s.\n", GetCabinetName());
553 
554  return false;
555 }
556 
557 
559 /*
560  * FUNCTION: Process cabinet
561  */
562 {
563  if (Verbose)
564  {
565  printf("ReactOS Cabinet Manager\n\n");
566  }
567 
568  switch (Mode)
569  {
570  case CM_MODE_CREATE:
571  return CreateCabinet();
572 
573  case CM_MODE_DISPLAY:
574  return DisplayCabinet();
575 
576  case CM_MODE_EXTRACT:
577  return ExtractFromCabinet();
578 
580  return CreateSimpleCabinet();
581 
582  default:
583  break;
584  }
585  return false;
586 }
587 
588 
589 /* Event handlers */
590 
592  char* FileName)
593 /*
594  * FUNCTION: Called when extracting a file and it already exists
595  * ARGUMENTS:
596  * File = Pointer to CFFILE for file being extracted
597  * Filename = Pointer to buffer with name of file (full path)
598  * RETURNS
599  * true if the file should be overwritten, false if not
600  */
601 {
602  if (Mode == CM_MODE_CREATE)
603  return true;
604 
605  /* Always overwrite */
606  return true;
607 }
608 
609 
611  char* FileName)
612 /*
613  * FUNCTION: Called just before extracting a file
614  * ARGUMENTS:
615  * File = Pointer to CFFILE for file being extracted
616  * FileName = Pointer to buffer with name of file (full path)
617  */
618 {
619  if (Verbose)
620  {
621  printf("Extracting %s\n", GetFileName(FileName));
622  }
623 }
624 
625 
626 
627 void CCABManager::OnDiskChange(char* CabinetName,
628  char* DiskLabel)
629  /*
630  * FUNCTION: Called when a new disk is to be processed
631  * ARGUMENTS:
632  * CabinetName = Pointer to buffer with name of cabinet
633  * DiskLabel = Pointer to buffer with label of disk
634  */
635 {
636  if (Verbose)
637  {
638  printf("\nChanging to cabinet %s - %s\n\n", CabinetName, DiskLabel);
639  }
640 }
641 
642 
644  char* FileName)
645 /*
646  * FUNCTION: Called just before adding a file to a cabinet
647  * ARGUMENTS:
648  * File = Pointer to CFFILE for file being added
649  * FileName = Pointer to buffer with name of file (full path)
650  */
651 {
652  if (Verbose)
653  {
654  printf("Adding %s\n", GetFileName(FileName));
655  }
656 }
657 
659 
660 int main(int argc, char * argv[])
661 /*
662  * FUNCTION: Main entry point
663  * ARGUMENTS:
664  * argc = Number of arguments on command line
665  * argv = Pointer to list of command line arguments
666  */
667 {
668  bool status = false;
669 
671 
672  return (status ? 0 : 1);
673 }
674 
675 /* EOF */
#define CAB_STATUS_INVALID_CAB
Definition: cabinet.h:31
void SetDestinationPath(char *DestinationPath)
Definition: cabinet.cxx:272
PCABINET_NAME CabinetName
Definition: dfp.h:122
static int argc
Definition: ServiceArgs.c:12
bool Run()
Definition: main.cxx:558
char * Pad(char *Str, char PadChar, ULONG Length)
Definition: main.cxx:29
ULONG FindFirst(PCAB_SEARCH Search)
Definition: cabinet.cxx:637
USHORT FileDate
Definition: cabinet.c:119
#define CM_MODE_DISPLAY
Definition: cabman.h:15
char * GetCabinetName()
Definition: cabinet.cxx:250
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
bool DontGenerateInf
Definition: dfp.h:71
virtual void OnDiskChange(char *CabinetName, char *DiskLabel)
Definition: main.cxx:627
PULONG FileCount
Definition: SfcGetFiles.c:18
bool IsCodecSelected()
Definition: cabinet.cxx:1098
void SetFileRelativePath(char *Path)
Definition: dfp.cxx:356
bool ParseCmdline(int argc, char *argv[])
Definition: main.cxx:223
#define CM_MODE_CREATE_SIMPLE
Definition: cabman.h:17
#define CAB_ATTRIB_SYSTEM
Definition: cabinet.c:63
#define CAB_ATTRIB_HIDDEN
Definition: cabinet.c:62
USHORT FileTime
Definition: cabinet.c:120
bool SetCompressionCodec(char *CodecName)
Definition: cabinet.cxx:361
int main(int argc, char *argv[])
Definition: main.cxx:660
#define argv
Definition: mplay32.c:18
bool ProcessAll
Definition: cabman.h:40
ULONG DebugTraceLevel
Definition: ndis.c:27
bool ExtractFromCabinet()
Definition: main.cxx:496
#define CAB_FILE_CONTINUED
Definition: cabinet.c:71
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define CAB_CODEC_MSZIP
Definition: cabinet.h:48
GLenum GLclampf GLint i
Definition: glfuncs.h:14
bool SetCabinetReservedFile(char *FileName)
Definition: cabinet.cxx:392
virtual void OnAdd(PCFFILE Entry, char *FileName)
Definition: main.cxx:643
USHORT Attributes
Definition: cabinet.c:121
ULONG Mode
Definition: cabman.h:41
char * GetFileName(char *Path)
Definition: cabinet.cxx:183
ULONG Open()
Definition: cabinet.cxx:470
#define CAB_STATUS_CANNOT_WRITE
Definition: cabinet.h:29
void Usage()
Definition: main.cxx:188
CCABManager()
Definition: main.cxx:167
bool DisplayCabinet()
Definition: main.cxx:427
unsigned char
Definition: typeof.h:27
#define CAB_ATTRIB_READONLY
Definition: cabinet.c:61
char * Date2Str(char *Str, USHORT Date)
Definition: main.cxx:55
char * Time2Str(char *Str, USHORT Time)
Definition: main.cxx:86
#define CM_MODE_CREATE
Definition: cabman.h:14
#define CAB_STATUS_UNSUPPCOMP
Definition: cabinet.h:33
bool InfFileOnly
Definition: dfp.h:70
void DestroySearchCriteria()
Definition: cabinet.cxx:327
unsigned int UINT
Definition: ndis.h:50
virtual void OnExtract(PCFFILE File, char *FileName)
Definition: main.cxx:610
#define Len
Definition: deflate.h:82
REFIID LPVOID DWORD dw
Definition: atlbase.h:40
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ULONG AddSearchCriteria(char *SearchCriteria)
Definition: cabinet.cxx:285
ULONG Parse()
Definition: dfp.cxx:195
#define CAB_STATUS_SUCCESS
Definition: cabinet.h:23
ULONG ExtractFile(char *FileName)
Definition: cabinet.cxx:738
ULONG FindNext(PCAB_SEARCH Search)
Definition: cabinet.cxx:652
void SelectCodec(LONG Id)
Definition: cabinet.cxx:1108
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static void ShowUsage(int ExitCode)
Definition: msiexec.c:59
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1060
Status
Definition: gdiplustypes.h:24
char * Attr2Str(char *Str, USHORT Attr)
Definition: main.cxx:126
#define CAB_ATTRIB_ARCHIVE
Definition: cabinet.c:66
bool HasSearchCriteria()
Definition: cabinet.cxx:351
unsigned short USHORT
Definition: pedump.c:61
char * FileName
Definition: cabinet.h:240
PCFFILE File
Definition: cabinet.h:76
virtual bool OnOverwrite(PCFFILE File, char *FileName)
Definition: main.cxx:591
bool CreateCabinet()
Definition: main.cxx:408
virtual ~CCABManager()
Definition: main.cxx:180
bool CreateSimpleCabinet()
Definition: cabinet.cxx:1683
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
#define MIN_TRACE
Definition: debug.h:14
ULONG FileSize
Definition: cabinet.c:116
bool Verbose
Definition: cabman.h:44
ULONG Load(char *FileName)
Definition: dfp.cxx:140
Definition: File.h:15
CCABManager CABMgr
Definition: main.cxx:658
#define memset(x, y, z)
Definition: compat.h:39
void SetCabinetName(char *FileName)
Definition: cabinet.cxx:261
static PLARGE_INTEGER Time
Definition: time.c:105
#define CM_MODE_EXTRACT
Definition: cabman.h:16
#define printf
Definition: config.h:203
USHORT FileControlID
Definition: blue.h:72
Definition: ps.c:97
PCABINET_NAME DiskLabel
Definition: dfp.h:129