Marcel Telka
2024-04-08 d6ccb6ab62f2f8726859d4d567e79af34435042f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/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()