1 /** @file
2 
3   Split a file into two pieces at the request offset.
4 
5 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 // GC_TODO: fix comment to start with /*++
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #ifdef __GNUC__
21 #include <unistd.h>
22 #else
23 #include <direct.h>
24 #endif
25 #include <ctype.h>
26 #include "ParseInf.h"
27 #include "CommonLib.h"
28 #include "EfiUtilityMsgs.h"
29 //
30 // Utility Name
31 //
32 #define UTILITY_NAME  "Split"
33 
34 //
35 // Utility version information
36 //
37 #define UTILITY_MAJOR_VERSION 1
38 #define UTILITY_MINOR_VERSION 0
39 
40 void
Version(void)41 Version (
42   void
43   )
44 /*++
45 
46 Routine Description:
47 
48   Displays the standard utility information to SDTOUT
49 
50 Arguments:
51 
52   None
53 
54 Returns:
55 
56   None
57 
58 --*/
59 {
60   printf ("%s Version %d.%d Build %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
61 }
62 
63 void
Usage(void)64 Usage (
65   void
66   )
67 /*++
68 
69 Routine Description:
70 
71   GC_TODO: Add function description
72 
73 Arguments:
74 
75 
76 Returns:
77 
78   GC_TODO: add return values
79 
80 --*/
81 {
82   Version();
83   printf ("Copyright (c) 1999-2016 Intel Corporation. All rights reserved.\n");
84   printf ("\n  SplitFile creates two Binary files either in the same directory as the current working\n");
85   printf ("  directory or in the specified directory.\n");
86   printf ("\nUsage: \n\
87    Split\n\
88      -f, --filename inputFile to split\n\
89      -s, --split VALUE the number of bytes in the first file\n\
90      [-p, --prefix OutputDir]\n\
91      [-o, --firstfile Filename1]\n\
92      [-t, --secondfile Filename2]\n\
93      [-v, --verbose]\n\
94      [--version]\n\
95      [-q, --quiet disable all messages except fatal errors]\n\
96      [-d, --debug[#]\n\
97      [-h, --help]\n");
98 }
99 
100 EFI_STATUS
GetSplitValue(IN CONST CHAR8 * SplitValueString,OUT UINT64 * ReturnValue)101 GetSplitValue (
102   IN CONST CHAR8* SplitValueString,
103   OUT UINT64 *ReturnValue
104 )
105 {
106   UINT64 len = strlen(SplitValueString);
107   UINT64 base = 1;
108   UINT64 index = 0;
109   UINT64 number = 0;
110   CHAR8 lastCHAR = 0;
111   EFI_STATUS Status = EFI_SUCCESS;
112 
113   if (len == 0) {
114     return EFI_ABORTED;
115   }
116 
117   Status = AsciiStringToUint64 (SplitValueString, FALSE, ReturnValue);
118   if (!EFI_ERROR (Status)) {
119     return Status;
120   }
121 
122   if (SplitValueString[0] == '0' && (SplitValueString[1] == 'x' || SplitValueString[1] == 'X')) {
123     Status = AsciiStringToUint64 (SplitValueString, TRUE, ReturnValue);
124     if (!EFI_ERROR (Status)) {
125       return Status;
126     }
127   }
128 
129   lastCHAR = (CHAR8)toupper((int)SplitValueString[len - 1]);
130 
131   if (lastCHAR != 'K' && lastCHAR != 'M' && lastCHAR != 'G') {
132     return STATUS_ERROR;
133   }
134 
135   for (;index < len - 1; ++index) {
136     if (!isdigit((int)SplitValueString[index])) {
137       return EFI_ABORTED;
138     }
139   }
140 
141   number = atol (SplitValueString);
142   if (lastCHAR == 'K')
143     base = 1024;
144   else if (lastCHAR == 'M')
145     base = 1024*1024;
146   else
147     base = 1024*1024*1024;
148 
149   *ReturnValue = number*base;
150 
151   return EFI_SUCCESS;
152 }
153 
154 EFI_STATUS
CountVerboseLevel(IN CONST CHAR8 * VerboseLevelString,IN CONST UINT64 Length,OUT UINT64 * ReturnValue)155 CountVerboseLevel (
156   IN CONST CHAR8* VerboseLevelString,
157   IN CONST UINT64 Length,
158   OUT UINT64 *ReturnValue
159 )
160 {
161   UINT64 i = 0;
162   for (;i < Length; ++i) {
163     if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') {
164       return EFI_ABORTED;
165     }
166     ++(*ReturnValue);
167   }
168 
169   return EFI_SUCCESS;
170 }
171 
172 EFI_STATUS
CreateDir(IN OUT CHAR8 ** FullFileName)173 CreateDir (
174   IN OUT CHAR8** FullFileName
175 )
176 {
177   CHAR8* temp = *FullFileName;
178   CHAR8* start = temp;
179   CHAR8  tempchar;
180   UINT64 index = 0;
181 
182   for (;index < strlen(temp); ++index) {
183     if (temp[index] == '\\' || temp[index] == '/') {
184       if (temp[index + 1] != '\0') {
185         tempchar = temp[index + 1];
186         temp[index + 1] = 0;
187         if (chdir(start)) {
188           if (mkdir(start, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
189             return EFI_ABORTED;
190           }
191           chdir(start);
192         }
193         start = temp + index + 1;
194         temp[index] = '/';
195         temp[index + 1] = tempchar;
196       }
197     }
198   }
199 
200   return EFI_SUCCESS;
201 }
202 
203 int
main(int argc,char * argv[])204 main (
205   int argc,
206   char*argv[]
207   )
208 /*++
209 
210 Routine Description:
211 
212   GC_TODO: Add function description
213 
214 Arguments:
215 
216   argc  - GC_TODO: add argument description
217   ]     - GC_TODO: add argument description
218 
219 Returns:
220 
221   GC_TODO: add return values
222 
223 --*/
224 {
225   EFI_STATUS    Status = EFI_SUCCESS;
226   INTN          ReturnStatus = STATUS_SUCCESS;
227   FILE          *In;
228   CHAR8         *InputFileName = NULL;
229   CHAR8         *OutputDir = NULL;
230   CHAR8         *OutFileName1 = NULL;
231   CHAR8         *OutFileName2 = NULL;
232   UINT64        SplitValue = (UINT64) -1;
233   FILE          *Out1 = NULL;
234   FILE          *Out2 = NULL;
235   CHAR8         *OutName1 = NULL;
236   CHAR8         *OutName2 = NULL;
237   CHAR8         *CurrentDir = NULL;
238   UINT64        Index;
239   CHAR8         CharC;
240   UINT64        DebugLevel = 0;
241   UINT64        VerboseLevel = 0;
242 
243   SetUtilityName(UTILITY_NAME);
244   if (argc == 1) {
245     Usage();
246     return STATUS_ERROR;
247   }
248 
249   argc --;
250   argv ++;
251 
252   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
253     Usage();
254     return STATUS_SUCCESS;
255   }
256 
257   if (stricmp (argv[0], "--version") == 0) {
258     Version();
259     return STATUS_SUCCESS;
260   }
261 
262   while (argc > 0) {
263     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--prefix") == 0)) {
264       OutputDir = argv[1];
265       if (OutputDir == NULL) {
266         Warning (NULL, 0, 0, "NO output directory specified.", NULL);
267         return STATUS_ERROR;
268       }
269       argc -= 2;
270       argv += 2;
271       continue;
272     }
273 
274     if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--filename") == 0)) {
275       InputFileName = argv[1];
276       if (InputFileName == NULL) {
277         Error (NULL, 0, 0x1001, "NO Input file specified.", NULL);
278         return STATUS_ERROR;
279       }
280       argc -= 2;
281       argv += 2;
282       continue;
283     }
284 
285     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--split") == 0)) {
286       Status = GetSplitValue(argv[1], &SplitValue);
287       if (EFI_ERROR (Status)) {
288         Error (NULL, 0, 0x1003, "Input split value is not one valid integer.", NULL);
289         return STATUS_ERROR;
290       }
291       argc -= 2;
292       argv += 2;
293       continue;
294     }
295 
296     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--firstfile") == 0)) {
297       OutFileName1 = argv[1];
298       if (OutFileName1 == NULL) {
299         Warning (NULL, 0, 0, NULL, "No output file1 specified.");
300       }
301       argc -= 2;
302       argv += 2;
303       continue;
304     }
305 
306     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--secondfile") == 0)) {
307       OutFileName2 = argv[1];
308       if (OutFileName2 == NULL) {
309         Warning (NULL, 0, 0, NULL, "No output file2 specified.");
310       }
311       argc -= 2;
312       argv += 2;
313       continue;
314     }
315 
316     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
317       argc --;
318       argv ++;
319       continue;
320     }
321 
322     if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {
323       VerboseLevel = 1;
324       if (strlen(argv[0]) > 2) {
325         Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);
326         if (EFI_ERROR (Status)) {
327           Error (NULL, 0, 0x1003, NULL, "%s is invaild parameter!", argv[0]);
328           return STATUS_ERROR;
329         }
330       }
331 
332       argc --;
333       argv ++;
334       continue;
335     }
336 
337     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
338       Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);
339       if (EFI_ERROR (Status)) {
340         Error (NULL, 0, 0x1003, "Input debug level is not one valid integrator.", NULL);
341         return STATUS_ERROR;
342       }
343       argc -= 2;
344       argv += 2;
345       continue;
346     }
347     //
348     // Don't recognize the parameter.
349     //
350     Error (NULL, 0, 0x1003, NULL, "%s is invaild parameter!", argv[0]);
351     return STATUS_ERROR;
352   }
353 
354   if (InputFileName == NULL) {
355     Error (NULL, 0, 0x1001, "NO Input file specified.", NULL);
356     return STATUS_ERROR;
357   }
358 
359   In = fopen (LongFilePath (InputFileName), "rb");
360   if (In == NULL) {
361     // ("Unable to open file \"%s\"\n", InputFileName);
362     Error (InputFileName, 0, 1, "File open failure", NULL);
363     return STATUS_ERROR;
364   }
365 
366   if (OutFileName1 == NULL) {
367     OutName1 = (CHAR8*)malloc(strlen(InputFileName) + 16);
368     if (OutName1 == NULL) {
369       Warning (NULL, 0, 0, NULL, "Memory Allocation Fail.");
370       ReturnStatus = STATUS_ERROR;
371       goto Finish;
372     }
373     strcpy (OutName1, InputFileName);
374     strcat (OutName1, "1");
375     OutFileName1 = OutName1;
376 
377   }
378   if (OutFileName2 == NULL) {
379     OutName2 = (CHAR8*)malloc(strlen(InputFileName) + 16);
380     if (OutName2 == NULL) {
381       Warning (NULL, 0, 0, NULL, "Memory Allocation Fail.");
382       ReturnStatus = STATUS_ERROR;
383       goto Finish;
384     }
385     strcpy (OutName2, InputFileName);
386     strcat (OutName2, "2");
387     OutFileName2 = OutName2;
388 
389   }
390 
391   if (OutputDir != NULL) {
392     //OutputDirSpecified = TRUE;
393     if (chdir(OutputDir) != 0) {
394       Warning (NULL, 0, 0, NULL, "Change dir to OutputDir Fail.");
395       ReturnStatus = STATUS_ERROR;
396       goto Finish;
397     }
398   }
399 
400   CurrentDir = (CHAR8*)getcwd((CHAR8*)0, 0);
401   if (EFI_ERROR(CreateDir(&OutFileName1))) {
402       Error (OutFileName1, 0, 5, "Create Dir for File1 Fail.", NULL);
403       ReturnStatus = STATUS_ERROR;
404       goto Finish;
405   }
406   chdir(CurrentDir);
407 
408   if (EFI_ERROR(CreateDir(&OutFileName2))) {
409       Error (OutFileName2, 0, 5, "Create Dir for File2 Fail.", NULL);
410       ReturnStatus = STATUS_ERROR;
411       goto Finish;
412   }
413   chdir(CurrentDir);
414   free(CurrentDir);
415 
416   Out1 = fopen (LongFilePath (OutFileName1), "wb");
417   if (Out1 == NULL) {
418     // ("Unable to open file \"%s\"\n", OutFileName1);
419     Error (OutFileName1, 0, 1, "File open failure", NULL);
420     ReturnStatus = STATUS_ERROR;
421     goto Finish;
422   }
423 
424   Out2 = fopen (LongFilePath (OutFileName2), "wb");
425   if (Out2 == NULL) {
426     // ("Unable to open file \"%s\"\n", OutFileName2);
427     Error (OutFileName2, 0, 1, "File open failure", NULL);
428     ReturnStatus = STATUS_ERROR;
429     goto Finish;
430   }
431 
432   for (Index = 0; Index < SplitValue; Index++) {
433     CharC = (CHAR8) fgetc (In);
434     if (feof (In)) {
435       break;
436     }
437 
438     fputc (CharC, Out1);
439   }
440 
441   for (;;) {
442     CharC = (CHAR8) fgetc (In);
443     if (feof (In)) {
444       break;
445     }
446 
447     fputc (CharC, Out2);
448   }
449 
450 Finish:
451   if (OutName1 != NULL) {
452     free(OutName1);
453   }
454   if (OutName2 != NULL) {
455     free(OutName2);
456   }
457   if (In != NULL) {
458     fclose (In);
459   }
460   if (Out1 != NULL) {
461     fclose (Out1);
462   }
463   if (Out2 != NULL) {
464     fclose (Out2);
465   }
466 
467   return ReturnStatus;
468 }
469