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