Add files via upload
[PyCatFile.git] / catfile.py
blob48574d918ee2f1db83cc27e0535c1b8953c7267f
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 '''
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the Revised BSD License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 Revised BSD License for more details.
13 Copyright 2018-2024 Cool Dude 2k - http://idb.berlios.de/
14 Copyright 2018-2024 Game Maker 2k - http://intdb.sourceforge.net/
15 Copyright 2018-2024 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
17 $FileInfo: catfile.py - Last Update: 5/2/2024 Ver. 0.9.8 RC 1 - Author: cooldude2k $
18 '''
20 from __future__ import absolute_import, division, print_function, unicode_literals;
21 import sys, argparse, pycatfile, binascii;
23 rarfile_support = pycatfile.rarfile_support;
24 py7zr_support = pycatfile.py7zr_support;
26 if(sys.version[0]=="2"):
27 try:
28 from io import StringIO, BytesIO;
29 except ImportError:
30 try:
31 from cStringIO import StringIO;
32 from cStringIO import StringIO as BytesIO;
33 except ImportError:
34 from StringIO import StringIO;
35 from StringIO import StringIO as BytesIO;
36 elif(sys.version[0]>="3"):
37 from io import StringIO, BytesIO;
38 else:
39 teststringio = 0;
40 if(teststringio<=0):
41 try:
42 from cStringIO import StringIO as BytesIO;
43 teststringio = 1;
44 except ImportError:
45 teststringio = 0;
46 if(teststringio<=0):
47 try:
48 from StringIO import StringIO as BytesIO;
49 teststringio = 2;
50 except ImportError:
51 teststringio = 0;
52 if(teststringio<=0):
53 try:
54 from io import BytesIO;
55 teststringio = 3;
56 except ImportError:
57 teststringio = 0;
59 __project__ = pycatfile.__project__;
60 __program_name__ = pycatfile.__program_name__;
61 __file_format_name__ = pycatfile.__file_format_name__;
62 __file_format_lower__ = pycatfile.__file_format_lower__;
63 __file_format_magic__ = pycatfile.__file_format_magic__;
64 __file_format_len__ = pycatfile.__file_format_len__;
65 __file_format_hex__ = pycatfile.__file_format_hex__;
66 __file_format_delimiter__ = pycatfile.__file_format_delimiter__;
67 __file_format_list__ = pycatfile.__file_format_list__;
68 __use_new_style__ = pycatfile.__use_new_style__;
69 __use_advanced_list__ = pycatfile.__use_advanced_list__;
70 __use_alt_inode__ = pycatfile.__use_alt_inode__;
71 __project_url__ = pycatfile.__project_url__;
72 __version_info__ = pycatfile.__version_info__;
73 __version_date_info__ = pycatfile.__version_date_info__;
74 __version_date__ = pycatfile.__version_date__;
75 __version_date_plusrc__ = pycatfile.__version_date_plusrc__;
76 __version__ = pycatfile.__version__;
78 # Initialize the argument parser
79 argparser = argparse.ArgumentParser(description="Manipulate concatenated files.", conflict_handler="resolve", add_help=True);
81 # Version information
82 argparser.add_argument("-V", "--version", action="version", version=__program_name__ + " " + __version__);
83 # Input and output specifications
84 argparser.add_argument("-i", "--input", help="Specify the file(s) to concatenate or the concatenated file to extract.", required=True);
85 argparser.add_argument("-o", "--output", default=None, help="Specify the name for the extracted or output concatenated files.");
86 # Operations
87 argparser.add_argument("-c", "--create", action="store_true", help="Perform only the concatenation operation.");
88 argparser.add_argument("-e", "--extract", action="store_true", help="Perform only the extraction operation.");
89 argparser.add_argument("-t", "--convert", action="store_true", help="Convert a tar/zip/rar/7zip file to a concatenated file.");
90 argparser.add_argument("-r", "--repack", action="store_true", help="Re-concatenate files, fixing checksum errors if any.");
91 # File manipulation options
92 argparser.add_argument("-F", "--format", default=__file_format_list__[0], help="Specify the format to use.");
93 argparser.add_argument("-D", "--delimiter", default=__file_format_list__[5], help="Specify the delimiter to use.");
94 argparser.add_argument("-m", "--formatver", default=__file_format_list__[6], help="Specify the format version.");
95 argparser.add_argument("-l", "--list", action="store_true", help="List files included in the concatenated file.");
96 # Compression options
97 argparser.add_argument("-P", "--compression", default="auto", help="Specify the compression method to use for concatenation.");
98 argparser.add_argument("-L", "--level", default=None, help="Specify the compression level for concatenation.");
99 # Checksum and validation
100 argparser.add_argument("-v", "--validate", action="store_true", help="Validate concatenated file checksums.");
101 argparser.add_argument("-C", "--checksum", default="crc32", help="Specify the type of checksum to use. The default is crc32.");
102 argparser.add_argument("-s", "--skipchecksum", action="store_true", help="Skip the checksum check of files.");
103 # Permissions and metadata
104 argparser.add_argument("-p", "--preserve", action="store_false", help="Do not preserve permissions and timestamps of files.");
105 # Miscellaneous
106 argparser.add_argument("-d", "--verbose", action="store_true", help="Enable verbose mode to display various debugging information.");
107 argparser.add_argument("-T", "--text", action="store_true", help="Read file locations from a text file.");
108 # Parse the arguments
109 getargs = argparser.parse_args();
111 fname = getargs.format;
112 fnamelower = fname.lower();
113 fnamemagic = fname;
114 fnamelen = len(fname);
115 fnamehex = binascii.hexlify(fname.encode("UTF-8")).decode("UTF-8");
116 fnamesty = __use_new_style__;
117 fnamelst = __use_advanced_list__;
118 fnameino = __use_alt_inode__;
119 fnamelist = [fname, fnamemagic, fnamelower, fnamelen, fnamehex, getargs.delimiter, getargs.formatver, fnamesty, fnamelst, fnameino];
121 # Determine the primary action based on user input
122 actions = ['create', 'extract', 'list', 'repack', 'validate'];
123 active_action = next((action for action in actions if getattr(getargs, action)), None);
125 # Execute the appropriate functions based on determined actions and arguments
126 if active_action:
127 if active_action=='create':
128 if getargs.convert:
129 checkcompressfile = pycatfile.CheckCompressionSubType(getargs.input, fnamelist, True);
130 if(checkcompressfile=="catfile"):
131 tmpout = pycatfile.RePackArchiveFile(getargs.input, getargs.output, getargs.compression, getargs.level, False, 0, 0, getargs.checksum, getargs.skipchecksum, [], fnamelist, getargs.verbose, False);
132 else:
133 tmpout = pycatfile.PackArchiveFileFromInFile(getargs.input, getargs.output, getargs.compression, getargs.level, getargs.checksum, [], fnamelist, getargs.verbose, False);
134 if(not tmpout):
135 sys.exit(1);
136 else:
137 pycatfile.PackArchiveFile(getargs.input, getargs.output, getargs.text, getargs.compression, getargs.level, False, getargs.checksum, [], fnamelist, getargs.verbose, False);
138 elif active_action=='repack':
139 if getargs.convert:
140 checkcompressfile = pycatfile.CheckCompressionSubType(getargs.input, fnamelist, True);
141 if(checkcompressfile=="catfile"):
142 pycatfile.RePackArchiveFile(getargs.input, getargs.output, getargs.compression, getargs.level, False, 0, 0, getargs.checksum, getargs.skipchecksum, [], fnamelist, getargs.verbose, False);
143 else:
144 pycatfile.PackArchiveFileFromInFile(getargs.input, getargs.output, getargs.compression, getargs.level, getargs.checksum, [], fnamelist, getargs.verbose, False);
145 if(not tmpout):
146 sys.exit(1);
147 else:
148 pycatfile.RePackArchiveFile(getargs.input, getargs.output, getargs.compression, getargs.level, False, 0, 0, getargs.checksum, getargs.skipchecksum, [], fnamelist, getargs.verbose, False);
149 elif active_action=='extract':
150 if getargs.convert:
151 checkcompressfile = pycatfile.CheckCompressionSubType(getargs.input, fnamelist, True);
152 tempout = BytesIO();
153 if(checkcompressfile=="catfile"):
154 tmpout = pycatfile.RePackArchiveFile(getargs.input, tempout, getargs.compression, getargs.level, False, 0, 0, getargs.checksum, getargs.skipchecksum, [], fnamelist, getargs.verbose, False);
155 else:
156 tmpout = pycatfile.PackArchiveFileFromInFile(getargs.input, tempout, getargs.compression, getargs.level, getargs.checksum, [], fnamelist, getargs.verbose, False);
157 if(not tmpout):
158 sys.exit(1);
159 getargs.input = tempout;
160 pycatfile.UnPackArchiveFile(getargs.input, getargs.output, False, 0, 0, getargs.skipchecksum, fnamelist, getargs.verbose, getargs.preserve, getargs.preserve, False);
161 elif active_action=='list':
162 if getargs.convert:
163 checkcompressfile = pycatfile.CheckCompressionSubType(getargs.input, fnamelist, True);
164 if(checkcompressfile=="catfile"):
165 tmpout = pycatfile.ArchiveFileListFiles(getargs.input, 0, 0, getargs.skipchecksum, fnamelist, getargs.verbose, False);
166 else:
167 tmpout = pycatfile.InFileListFiles(getargs.input, getargs.verbose, fnamelist, False);
168 if(not tmpout):
169 sys.exit(1);
170 else:
171 pycatfile.ArchiveFileListFiles(getargs.input, 0, 0, getargs.skipchecksum, fnamelist, getargs.verbose, False);
172 elif active_action=='validate':
173 if getargs.convert:
174 checkcompressfile = pycatfile.CheckCompressionSubType(getargs.input, fnamelist, True);
175 tempout = BytesIO();
176 if(checkcompressfile=="catfile"):
177 tmpout = pycatfile.RePackArchiveFile(getargs.input, tempout, getargs.compression, getargs.level, False, 0, 0, getargs.checksum, getargs.skipchecksum, [], fnamelist, getargs.verbose, False);
178 else:
179 tmpout = pycatfile.PackArchiveFileFromInFile(getargs.input, tempout, getargs.compression, getargs.level, getargs.checksum, [], fnamelist, getargs.verbose, False);
180 getargs.input = tempout;
181 if(not tmpout):
182 sys.exit(1);
183 fvalid = pycatfile.ArchiveFileValidate(getargs.input, fnamelist, getargs.verbose, False);
184 if(not getargs.verbose):
185 import sys, logging;
186 logging.basicConfig(format="%(message)s", stream=sys.stdout, level=logging.DEBUG);
187 if(fvalid):
188 pycatfile.VerbosePrintOut("File is valid: \n" + str(getargs.input));
189 else:
190 pycatfile.VerbosePrintOut("File is invalid: \n" + str(getargs.input));