#! /usr/bin/python3
# vim: set filetype=python:
'''Converts a RAR archive to a TAR archive and writes 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"
__version__ = "0.2.1"
__status__ = "Development"

import os
import sys

# Modules for tar and rar file handling
import tarfile
import rarfile

# For time calculation
import datetime
import time

# Set to '/' to be more compatible with zipfile
rarfile.PATH_SEP = '/'

# timestamps as datetime objects
rarfile.USE_DATETIME = 1

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

# Process arguments
if len(sys.argv) < 2:
    print_(__doc__)
    exit(1)

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

# 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 content of rared file to tar
    tarf.addfile(tarinfo, infile)

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