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