#! /usr/bin/python3
# vim: set filetype=python:

'''Convert a RAR archive to a TAR archive and write it to stdout.
usage: rar2tarcat [-h] rarfile > tarfile
'''
# This is a simplified version of rar2tar, which has more functions,
# but uses the module argument parser.

__authors__ = 'D. Gloger'
__maintainer__ = 'D. Gloger'  # with edits by B.Lindholm
__version__ = '0.2.2'
__status__ = 'Development'

# Modules for tar and rar file handling
import os, sys, datetime, time, tarfile, rarfile

# Print function with maximal compatibility.
def print_(s):
    sys.stdout.write(s+'\n')

# Process arguments
if len(sys.argv) < 2:
    print_(__doc__)
    sys.exit(1)
if sys.argv[1] in ('-h', '--help'):
    print_(__doc__)
    sys.exit(0)
elif sys.argv[1] in ('-V', '--version'):
    print_(os.path.basename(__file__)+' v'+__version__)
    sys.exit(0)

# Set path separator to '/' for more compatibility with zipfiles; use timestamps as datetime objects
rarfile.PATH_SEP = '/'
rarfile.USE_DATETIME = 1

# Input rarfile
infile = sys.argv[1]
# Read rarfile
rarf = rarfile.RarFile(infile, 'r')
# This simplified version can only write to the standard output
tarf = tarfile.open(fileobj=sys.stdout.buffer, mode='w|')

# Loop over all filenames
for rarinfo in rarf.infolist():

    # filename
    name = rarinfo.filename

    # add file info to tar
    tarinfo = tarfile.TarInfo(name)
    tarinfo.size = rarinfo.file_size

    # convert local time from RAR timestamp (as struct_time) ...
    local_time = datetime.datetime(*rarinfo.date_time).timetuple()
    # ... to TAR timestamp based on UTC time (as seconds since the epoch).
    tarinfo.mtime = time.mktime(local_time)

    # file mode
    if rarinfo.host_os == rarfile.RAR_OS_UNIX:
        tarinfo.mode = rarinfo.mode
    else:
        tarinfo.mode = 0o755 if rarinfo.isdir() else 0o644
    # directories:
    if rarinfo.isdir():
        tarinfo.type = tarfile.DIRTYPE
        infile = None
    else:
        tarinfo.type = tarfile.REGTYPE
        infile = rarf.open(rarinfo.filename, 'r')

    # write contents of file to tar
    tarf.addfile(tarinfo, infile)

# Close both archives
tarf.close()
rarf.close()
