blob: e70d5c22c4681fe621b4c0c40e335639b5280bca [file] [log] [blame]
# @file
# Split a file into two pieces at the request offset.
#
# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
# Import Modules
#
import argparse
import os
import io
import shutil
import logging
import sys
import tempfile
parser = argparse.ArgumentParser(description='''
SplitFile creates two Binary files either in the same directory as the current working directory or in the specified directory.
''')
parser.add_argument("-f", "--filename", dest="inputfile",
required=True, help="The input file to split tool.")
parser.add_argument("-s", "--split", dest="position",
required=True, help="The number of bytes in the first file. The valid format are HEX, Decimal and Decimal[KMG].")
parser.add_argument("-p", "--prefix", dest="output",
help="The output folder.")
parser.add_argument("-o", "--firstfile", help="The first file name")
parser.add_argument("-t", "--secondfile", help="The second file name")
parser.add_argument("--version", action="version", version='%(prog)s Version 2.0',
help="Print debug information.")
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true",
help="Print debug information.")
group.add_argument("-q", "--quiet", action="store_true",
help="Disable all messages except fatal errors")
SizeDict = {
"K": 1024,
"M": 1024*1024,
"G": 1024*1024*1024
}
def GetPositionValue(position):
'''
Parse the string of the argument position and return a decimal number.
The valid position formats are
1. HEX
e.g. 0x1000 or 0X1000
2. Decimal
e.g. 100
3. Decimal[KMG]
e.g. 100K or 100M or 100G or 100k or 100m or 100g
'''
logger = logging.getLogger('Split')
PosVal = 0
header = position[:2].upper()
tailer = position[-1].upper()
try:
if tailer in SizeDict:
PosVal = int(position[:-1]) * SizeDict[tailer]
else:
if header == "0X":
PosVal = int(position, 16)
else:
PosVal = int(position)
except Exception as e:
logger.error(
"The parameter %s format is incorrect. The valid format is HEX, Decimal and Decimal[KMG]." % position)
raise(e)
return PosVal
def getFileSize(filename):
'''
Read the input file and return the file size.
'''
logger = logging.getLogger('Split')
length = 0
try:
with open(filename, "rb") as fin:
fin.seek(0, io.SEEK_END)
length = fin.tell()
except Exception as e:
logger.error("Access file failed: %s", filename)
raise(e)
return length
def getoutputfileabs(inputfile, prefix, outputfile,index):
inputfile = os.path.abspath(inputfile)
if outputfile is None:
if prefix is None:
outputfileabs = os.path.join(os.path.dirname(inputfile), "{}{}".format(os.path.basename(inputfile),index))
else:
if os.path.isabs(prefix):
outputfileabs = os.path.join(prefix, "{}{}".format(os.path.basename(inputfile),index))
else:
outputfileabs = os.path.join(os.getcwd(), prefix, "{}{}".format(os.path.basename(inputfile),index))
elif not os.path.isabs(outputfile):
if prefix is None:
outputfileabs = os.path.join(os.getcwd(), outputfile)
else:
if os.path.isabs(prefix):
outputfileabs = os.path.join(prefix, outputfile)
else:
outputfileabs = os.path.join(os.getcwd(), prefix, outputfile)
else:
outputfileabs = outputfile
return outputfileabs
def splitFile(inputfile, position, outputdir=None, outputfile1=None, outputfile2=None):
'''
Split the inputfile into outputfile1 and outputfile2 from the position.
'''
logger = logging.getLogger('Split')
if not os.path.exists(inputfile):
logger.error("File Not Found: %s" % inputfile)
raise(Exception)
if outputfile1 and outputfile2 and outputfile1 == outputfile2:
logger.error(
"The firstfile and the secondfile can't be the same: %s" % outputfile1)
raise(Exception)
# Create dir for the output files
try:
outputfile1 = getoutputfileabs(inputfile, outputdir, outputfile1,1)
outputfolder = os.path.dirname(outputfile1)
if not os.path.exists(outputfolder):
os.makedirs(outputfolder)
outputfile2 = getoutputfileabs(inputfile, outputdir, outputfile2,2)
outputfolder = os.path.dirname(outputfile2)
if not os.path.exists(outputfolder):
os.makedirs(outputfolder)
except Exception as e:
logger.error("Can't make dir: %s" % outputfolder)
raise(e)
if position <= 0:
if outputfile2 != os.path.abspath(inputfile):
shutil.copyfile(os.path.abspath(inputfile), outputfile2)
with open(outputfile1, "wb") as fout:
fout.write(b'')
else:
inputfilesize = getFileSize(inputfile)
if position >= inputfilesize:
if outputfile1 != os.path.abspath(inputfile):
shutil.copyfile(os.path.abspath(inputfile), outputfile1)
with open(outputfile2, "wb") as fout:
fout.write(b'')
else:
try:
tempdir = tempfile.mkdtemp()
tempfile1 = os.path.join(tempdir, "file1.bin")
tempfile2 = os.path.join(tempdir, "file2.bin")
with open(inputfile, "rb") as fin:
content1 = fin.read(position)
with open(tempfile1, "wb") as fout1:
fout1.write(content1)
content2 = fin.read(inputfilesize - position)
with open(tempfile2, "wb") as fout2:
fout2.write(content2)
shutil.copyfile(tempfile1, outputfile1)
shutil.copyfile(tempfile2, outputfile2)
except Exception as e:
logger.error("Split file failed")
raise(e)
finally:
if os.path.exists(tempdir):
shutil.rmtree(tempdir)
def main():
args = parser.parse_args()
status = 0
logger = logging.getLogger('Split')
if args.quiet:
logger.setLevel(logging.CRITICAL)
if args.verbose:
logger.setLevel(logging.DEBUG)
lh = logging.StreamHandler(sys.stdout)
lf = logging.Formatter("%(levelname)-8s: %(message)s")
lh.setFormatter(lf)
logger.addHandler(lh)
try:
position = GetPositionValue(args.position)
splitFile(args.inputfile, position, args.output,
args.firstfile, args.secondfile)
except Exception as e:
status = 1
return status
if __name__ == "__main__":
exit(main())