#!/usr/bin/python3.9
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2010, Oracle and/or it's affiliates.  All rights reserved.
# Copyright (c) 2018-2019, Michal Nowak
#
#
# unpack.py - an archive unpack utility
#
#  A simple program to uncompress and unpack source archive files into a target
#  directory and fix permissions if requested.
#

import os
import sys

def uncompress_unpack_commands(filename, verbose=False):
	import re

	uncompress = "/bin/cat"

	if (re.search("(\.bz2|\.tbz|\.tbz2)$", filename) != None):
		uncompress = "/usr/bin/bzip2 -dc"
	elif (re.search("(\.gz|\.tgz)$", filename) != None):
		uncompress = "/usr/bin/gzip -dc"
	elif (re.search("(\.Z)$", filename) != None):
		uncompress = "/usr/bin/uncompress -c"
	elif (re.search("(\.7z)$", filename) != None):
		uncompress = "/usr/bin/7z x"
	elif (re.search("(\.lz)$", filename) != None):
		uncompress = "/usr/bin/lzip -dc"
	elif (re.search("(\.xz)$", filename) != None):
		uncompress = "/usr/bin/xz -dc"
	elif (re.search("(\.zip)$", filename) != None):
		uncompress = "/usr/bin/unzip -qo"
	elif (re.search("(\.oxt)$", filename) != None):
		uncompress = "/usr/bin/unzip -qo"
	elif (re.search("(\.zst|\.tzst)$", filename) != None):
		uncompress = "/usr/bin/unzstd -c"
	elif (re.search("(\.gem)$", filename) != None):
		ruby_ver = os.getenv('RUBY_VERSION', '')
		uncompress = "/usr/ruby/" + ruby_ver + "/bin/gem unpack"

	# if the file is just compressed, redirect stdout to ./filename with
	# one less extension.
	unpack = " > ./" + '.'.join(os.path.basename(filename).split('.')[:-1])

	if (re.search("(\.tar\.[^\.]+|\.tgz|\.txz|\.tbz2?)$",filename) != None):
		unpack = " | gtar -xf -"
	elif (re.search("(\.zip)$", filename) != None):
		unpack = ""
	elif (re.search("(\.oxt)$", filename) != None):
		unpack = ""
	elif (re.search("(\.jar)$", filename) != None):
		unpack = " | jar xf -"
	elif (re.search("(\.gem)$", filename) != None):
		unpack = ""

	if (verbose == True):
		print("command: %s %s%s" % (uncompress, filename, unpack))

	return uncompress, unpack

#
# recurse down a directory tree opening permissions so that others may access
# files in the tree.
#
def fixup_permissions(dir, verbose):
	for entry in os.listdir(dir):
		import stat

		path = "%s/%s" % (dir, entry)

		st = os.lstat(path)
		mode = stat.S_IMODE(st.st_mode)
		mode |= (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
		if stat.S_ISDIR(st.st_mode):
			mode |= (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)

		if (stat.S_IMODE(st.st_mode) != mode):
			if (verbose == True):
				print("Changing %s from %4.4o to %4.4o" % (path,
						stat.S_IMODE(st.st_mode), mode))
			os.chmod(path, mode)

		if stat.S_ISDIR(st.st_mode):
			fixup_permissions(path, verbose)


def usage():
	print("Usage: %s [-v|--verbose] [-f|--fix-permissions] [-r|--relocate-to (dir)] (file)" % (sys.argv[0].split('/')[-1]))
	sys.exit(1)

def main():
	import getopt
	import sys
	import tempfile

	verbose = False
	permissions = None
	relocate_to = None

	if len(sys.argv) == 1:
		usage()

	try:
		opts, args = getopt.getopt(sys.argv[1:], "fr:v",
			["fix-permissions", "relocate-to=", "verbose"])
	except getopt.GetoptError as err:
		print(str(err))
		usage()

	for opt, arg in opts:
		if opt in [ "-v", "--verbose" ]:
			verbose = True
		elif opt in [ "-f", "--fix-permissions" ]:
			permissions = True
		elif opt in [ "-r", "--relocate-to" ]:
			relocate_to = arg
		else:
			assert False, "unknown option"

	filename = ((args[0][0] == '/') and "%s" or "../%s") % args[0]
	uncompress, unpack = uncompress_unpack_commands(filename)
	tempdir = tempfile.mkdtemp(dir='.')

	# extract the archive contents
	if (verbose == True):	
		print("cd %s ; %s %s%s" % (tempdir, uncompress, filename,
						unpack))
	os.system("cd %s ; %s %s%s" % (tempdir, uncompress, filename, unpack))

	# open up the permissions on what we extracted
	if permissions:
		fixup_permissions(tempdir, verbose)

	if (relocate_to == None):
		# move everything in the tempdir here
		for entry in os.listdir(tempdir):
			path= "%s/%s" % (tempdir, entry)
			os.renames(path, entry)
	else:
		# rename the tempdir and open it's permissions
		os.renames(tempdir, relocate_to)
		os.chmod(relocate_to, 0o755)


if __name__ == "__main__":
	main()