1 /*
2 *
3 * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
4 *
5
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26 // C++ Standard Library
27 #include <QCoreApplication>
28
29 // STL
30 #include <iostream>
31 #include <unistd.h>
32
33 // LibArchive
34 #include "libarchiveqt.h"
35
36 /* To pretty print file sizes */
formatSize(qint64 num)37 QString formatSize( qint64 num ) {
38
39 QString total;
40 const qint64 kb = 1024;
41 const qint64 mb = 1024 * kb;
42 const qint64 gb = 1024 * mb;
43 const qint64 tb = 1024 * gb;
44
45 if ( num >= tb ) total = QString( "%1 TiB" ).arg( QString::number( qreal( num ) / tb, 'f', 3 ) );
46 else if ( num >= gb ) total = QString( "%1 GiB" ).arg( QString::number( qreal( num ) / gb, 'f', 2 ) );
47 else if ( num >= mb ) total = QString( "%1 MiB" ).arg( QString::number( qreal( num ) / mb, 'f', 1 ) );
48 else if ( num >= kb ) total = QString( "%1 KiB" ).arg( QString::number( qreal( num ) / kb,'f',1 ) );
49 else total = QString( "%1 byte%2" ).arg( num ).arg( num > 1 ? "s": "" );
50
51 return total;
52 };
53
54 /* Pretty print the usage */
printUsage(const char * exec)55 void printUsage( const char *exec ) {
56
57 std::cout << "Archiver v2.0.4\n" << std::endl;
58
59 std::cout << "Usage:\n\t" << exec << " -c archive.xxx file1 file2 file3 ..." << std::endl;
60 std::cout << "\t" << exec << " -d archive.xxx output_dir" << std::endl;
61 std::cout << "\t" << exec << " -m archive.xxx member_name output_dir" << std::endl;
62 std::cout << "\t" << exec << " -l archive.xxx" << std::endl;
63 };
64
main(int argc,char ** argv)65 int main( int argc, char** argv ) {
66
67 /* Init the QApplication instance */
68 QCoreApplication app( argc, argv);
69
70 /*
71 *
72 * We need three arguments at minimum
73 * 1. The program name (argv[ 0 ]) => Always existing
74 * 2. The switch: one of c, d, m or l: Tells the program what to do
75 * 3. The archive name to operate on (list or decompress)
76 * In case we are compressing or extracting a member, an additional argument is necessary
77 *
78 */
79 if ( argc < 3 ) {
80
81 printUsage( argv[ 0 ] );
82 return 1;
83 }
84
85 /* Print help text or usage */
86 else if ( ( argc == 2 ) and ( strcmp( argv[ 1 ], "-h" ) == 0 ) ) {
87
88 printUsage( argv[ 0 ] );
89 return 0;
90 }
91
92 /* Print help text or usage */
93 else if ( ( argc == 2 ) and ( strcmp( argv[ 1 ], "--help" ) == 0 ) ) {
94
95 printUsage( argv[ 0 ] );
96 return 0;
97 }
98
99 /* Switch c, but no input files mentioned */
100 else if ( ( argc == 3 ) and ( strcmp( argv[ 1 ], "-c" ) == 0 ) ) {
101
102 printUsage( argv[ 0 ] );
103
104 std::cout << "\nArchiver: ERROR: No input files specified." << std::endl;
105 return 1;
106 }
107
108 /* Switch m, but no member name mentioned */
109 else if ( ( argc < 4 ) and ( strcmp( argv[ 1 ], "-m" ) == 0 ) ) {
110
111 printUsage( argv[ 0 ] );
112
113 std::cout << "\nArchiver: ERROR: No member name specified." << std::endl;
114 return 1;
115 }
116
117 /* Excess arguments */
118 else if ( ( argc > 3 ) and ( strcmp( argv[ 1 ], "-l" ) == 0 ) ) {
119
120 printUsage( argv[ 0 ] );
121
122 std::cout << "\nArchiver: ERROR: Too many files specified" << std::endl;
123 return 1;
124 }
125
126 /* No switch mentioned */
127 else if ( ( argc >= 3 ) and strcmp( argv[ 1 ], "-c" ) and strcmp( argv[ 1 ], "-d" ) and strcmp( argv[ 1 ], "-l" ) and strcmp( argv[ 1 ], "-m" ) ) {
128
129 printUsage( argv[ 0 ] );
130
131 std::cout << "\nArchiver: ERROR: You need to specify one of -c, -d, -m or -l" << std::endl;
132 return 1;
133 }
134
135 /* Compress the input files argv[3+] into archive argv[2] */
136 else if ( strcmp( argv[ 1 ], "-c" ) == 0 ) {
137
138 // Write archive code
139 LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
140
141 arc->updateInputFiles( app.arguments().mid( 3 ), LibArchiveQt::RelativeToCurrent );
142 arc->createArchive();
143 arc->waitForFinished();
144
145 return 0;
146 }
147
148 /* Decompress the archive argv[2] optionally to argv[3] */
149 else if ( strcmp( argv[ 1 ], "-d" ) == 0 ) {
150
151 // Read archive code
152 LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
153
154 if ( argc >= 4 )
155 arc->setDestination( argv[ 3 ] );
156
157 arc->extractArchive();
158 arc->waitForFinished();
159
160 return 0;
161 }
162
163 /* Decompress the member argv[3] optionally to argv[4] from archive argv[2] */
164 else if ( strcmp( argv[ 1 ], "-m" ) == 0 ) {
165
166 // Read archive code
167 LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
168
169 if ( argc == 5 ) {
170 arc->setDestination( argv[ 3 ] );
171 arc->extractMember( argv[ 4 ] );
172 }
173 else {
174 arc->extractMember( argv[ 3 ] );
175 }
176
177 arc->waitForFinished();
178 return 0;
179 }
180
181 /* List archive argv[2] */
182 else if ( strcmp( argv[ 1 ], "-l" ) == 0 ) {
183
184 // List archive code
185 LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
186
187 int length = 0;
188 Q_FOREACH( ArchiveEntry *ae, arc->listArchive() )
189 length = ( ae->name.length() > length ? ae->name.length() : length );
190
191 Q_FOREACH( ArchiveEntry *ae, arc->listArchive() ) {
192 if ( ae->type == AE_IFREG )
193 qDebug() << ae->name.rightJustified( length + 10 ).toLocal8Bit().data() << " " << formatSize( ae->size ).toLocal8Bit().data();
194
195 else
196 qDebug() << ae->name.rightJustified( length + 10 ).toLocal8Bit().data();
197 }
198
199 arc->waitForFinished();
200
201 return 0;
202 }
203
204 /* Print help text */
205 else {
206
207 printUsage( argv[ 0 ] );
208 return 0;
209 }
210 };
211