1/** @file
2
3  Split a file into two pieces at the request offset.
4
5Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.<BR>
6This program and the accompanying materials are licensed and made available
7under the terms and conditions of the BSD License which accompanies this
8distribution.  The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT 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 0
38#define UTILITY_MINOR_VERSION 1
39
40void
41Version (
42  void
43  )
44/*++
45
46Routine Description:
47
48  Displays the standard utility information to SDTOUT
49
50Arguments:
51
52  None
53
54Returns:
55
56  None
57
58--*/
59{
60  printf ("%s Version %d.%d %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
61  printf ("Copyright (c) 1999-2015 Intel Corporation. All rights reserved.\n");
62  printf ("\n  SplitFile creates two Binary files either in the same directory as the current working\n");
63  printf ("  directory or in the specified directory.\n");
64}
65
66void
67Usage (
68  void
69  )
70/*++
71
72Routine Description:
73
74  GC_TODO: Add function description
75
76Arguments:
77
78
79Returns:
80
81  GC_TODO: add return values
82
83--*/
84{
85  Version();
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
100EFI_STATUS
101GetSplitValue (
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
154EFI_STATUS
155CountVerboseLevel (
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
172EFI_STATUS
173CreateDir (
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
203int
204main (
205  int argc,
206  char*argv[]
207  )
208/*++
209
210Routine Description:
211
212  GC_TODO: Add function description
213
214Arguments:
215
216  argc  - GC_TODO: add argument description
217  ]     - GC_TODO: add argument description
218
219Returns:
220
221  GC_TODO: add return values
222
223--*/
224{
225  EFI_STATUS    Status = EFI_SUCCESS;
226  FILE          *In;
227  CHAR8         *InputFileName = NULL;
228  CHAR8         *OutputDir = NULL;
229  CHAR8         *OutFileName1 = NULL;
230  CHAR8         *OutFileName2 = NULL;
231  UINT64        SplitValue = (UINT64) -1;
232  FILE          *Out1;
233  FILE          *Out2;
234  CHAR8         *OutName1 = NULL;
235  CHAR8         *OutName2 = NULL;
236  CHAR8         *CurrentDir = NULL;
237  UINT64        Index;
238  CHAR8         CharC;
239  UINT64        DebugLevel = 0;
240  UINT64        VerboseLevel = 0;
241
242  SetUtilityName(UTILITY_NAME);
243  if (argc == 1) {
244    Usage();
245    return STATUS_ERROR;
246  }
247
248  argc --;
249  argv ++;
250
251  if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
252    Usage();
253    return STATUS_SUCCESS;
254  }
255
256  if (stricmp (argv[0], "--version") == 0) {
257    Version();
258    return STATUS_SUCCESS;
259  }
260
261  while (argc > 0) {
262    if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--prefix") == 0)) {
263      OutputDir = argv[1];
264      if (OutputDir == NULL) {
265        Warning (NULL, 0, 0, "NO output directory specified.", NULL);
266        return STATUS_ERROR;
267      }
268      argc -= 2;
269      argv += 2;
270      continue;
271    }
272
273    if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--filename") == 0)) {
274      InputFileName = argv[1];
275      if (InputFileName == NULL) {
276        Error (NULL, 0, 0x1001, "NO Input file specified.", NULL);
277        return STATUS_ERROR;
278      }
279      argc -= 2;
280      argv += 2;
281      continue;
282    }
283
284    if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--split") == 0)) {
285      Status = GetSplitValue(argv[1], &SplitValue);
286      if (EFI_ERROR (Status)) {
287        Error (NULL, 0, 0x1003, "Input split value is not one valid integer.", NULL);
288        return STATUS_ERROR;
289      }
290      argc -= 2;
291      argv += 2;
292      continue;
293    }
294
295    if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--firstfile") == 0)) {
296      OutFileName1 = argv[1];
297      if (OutFileName1 == NULL) {
298        Warning (NULL, 0, 0, NULL, "No output file1 specified.");
299      }
300      argc -= 2;
301      argv += 2;
302      continue;
303    }
304
305    if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--secondfile") == 0)) {
306      OutFileName2 = argv[1];
307      if (OutFileName2 == NULL) {
308        Warning (NULL, 0, 0, NULL, "No output file2 specified.");
309      }
310      argc -= 2;
311      argv += 2;
312      continue;
313    }
314
315    if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
316      argc --;
317      argv ++;
318      continue;
319    }
320
321    if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {
322      VerboseLevel = 1;
323      if (strlen(argv[0]) > 2) {
324        Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);
325        if (EFI_ERROR (Status)) {
326          Error (NULL, 0, 0x1003, NULL, "%s is invaild paramter!", argv[0]);
327          return STATUS_ERROR;
328        }
329      }
330
331      argc --;
332      argv ++;
333      continue;
334    }
335
336    if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
337      Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);
338      if (EFI_ERROR (Status)) {
339        Error (NULL, 0, 0x1003, "Input debug level is not one valid integrator.", NULL);
340        return STATUS_ERROR;
341      }
342      argc -= 2;
343      argv += 2;
344      continue;
345    }
346    //
347    // Don't recognize the paramter.
348    //
349    Error (NULL, 0, 0x1003, NULL, "%s is invaild paramter!", argv[0]);
350    return STATUS_ERROR;
351  }
352
353  if (InputFileName == NULL) {
354    Error (NULL, 0, 0x1001, "NO Input file specified.", NULL);
355    return STATUS_ERROR;
356  }
357
358  In = fopen (LongFilePath (InputFileName), "rb");
359  if (In == NULL) {
360    // ("Unable to open file \"%s\"\n", InputFileName);
361    Error (InputFileName, 0, 1, "File open failure", NULL);
362    return STATUS_ERROR;
363  }
364
365  if (OutFileName1 == NULL) {
366    OutName1 = (CHAR8*)malloc(strlen(InputFileName) + 16);
367    if (OutName1 == NULL) {
368      Warning (NULL, 0, 0, NULL, "Memory Allocation Fail.");
369      return STATUS_ERROR;
370    }
371    strcpy (OutName1, InputFileName);
372    strcat (OutName1, "1");
373    OutFileName1 = OutName1;
374
375  }
376  if (OutFileName2 == NULL) {
377    OutName2 = (CHAR8*)malloc(strlen(InputFileName) + 16);
378    if (OutName2 == NULL) {
379      Warning (NULL, 0, 0, NULL, "Memory Allocation Fail.");
380      return STATUS_ERROR;
381    }
382    strcpy (OutName2, InputFileName);
383    strcat (OutName2, "2");
384    OutFileName2 = OutName2;
385
386  }
387
388  if (OutputDir != NULL) {
389    //OutputDirSpecified = TRUE;
390    if (chdir(OutputDir) != 0) {
391      Warning (NULL, 0, 0, NULL, "Change dir to OutputDir Fail.");
392      return STATUS_ERROR;
393    }
394  }
395
396  CurrentDir = (CHAR8*)getcwd((CHAR8*)0, 0);
397  if (EFI_ERROR(CreateDir(&OutFileName1))) {
398      Error (OutFileName1, 0, 5, "Create Dir for File1 Fail.", NULL);
399      return STATUS_ERROR;
400  }
401  chdir(CurrentDir);
402
403  if (EFI_ERROR(CreateDir(&OutFileName2))) {
404      Error (OutFileName2, 0, 5, "Create Dir for File2 Fail.", NULL);
405      return STATUS_ERROR;
406  }
407  chdir(CurrentDir);
408  free(CurrentDir);
409
410  Out1 = fopen (LongFilePath (OutFileName1), "wb");
411  if (Out1 == NULL) {
412    // ("Unable to open file \"%s\"\n", OutFileName1);
413    Error (OutFileName1, 0, 1, "File open failure", NULL);
414    return STATUS_ERROR;
415  }
416
417  Out2 = fopen (LongFilePath (OutFileName2), "wb");
418  if (Out2 == NULL) {
419    // ("Unable to open file \"%s\"\n", OutFileName2);
420    Error (OutFileName2, 0, 1, "File open failure", NULL);
421    return STATUS_ERROR;
422  }
423
424  for (Index = 0; Index < SplitValue; Index++) {
425    CharC = (CHAR8) fgetc (In);
426    if (feof (In)) {
427      break;
428    }
429
430    fputc (CharC, Out1);
431  }
432
433  for (;;) {
434    CharC = (CHAR8) fgetc (In);
435    if (feof (In)) {
436      break;
437    }
438
439    fputc (CharC, Out2);
440  }
441
442  if (OutName1 != NULL) {
443    free(OutName1);
444  }
445  if (OutName2 != NULL) {
446    free(OutName2);
447  }
448  fclose (In);
449  fclose (Out1);
450  fclose (Out2);
451
452  return STATUS_SUCCESS;
453}
454