1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // clang-format off
16 /*-
17 * This is a compact "tar" program whose primary goal is small size.
18 * Statically linked, it can be very small indeed. This serves a number
19 * of goals:
20 * o a testbed for libarchive (to check for link pollution),
21 * o a useful tool for space-constrained systems (boot floppies, etc),
22 * o a place to experiment with new implementation ideas for bsdtar,
23 * o a small program to demonstrate libarchive usage.
24 *
25 * Use the following macros to suppress features:
26 * NO_BZIP2 - Implies NO_BZIP2_CREATE and NO_BZIP2_EXTRACT
27 * NO_BZIP2_CREATE - Suppress bzip2 compression support.
28 * NO_BZIP2_EXTRACT - Suppress bzip2 auto-detection and decompression.
29 * NO_COMPRESS - Implies NO_COMPRESS_CREATE and NO_COMPRESS_EXTRACT
30 * NO_COMPRESS_CREATE - Suppress compress(1) compression support
31 * NO_COMPRESS_EXTRACT - Suppress compress(1) auto-detect and decompression.
32 * NO_CREATE - Suppress all archive creation support.
33 * NO_CPIO_EXTRACT - Suppress auto-detect and dearchiving of cpio archives.
34 * NO_GZIP - Implies NO_GZIP_CREATE and NO_GZIP_EXTRACT
35 * NO_GZIP_CREATE - Suppress gzip compression support.
36 * NO_GZIP_EXTRACT - Suppress gzip auto-detection and decompression.
37 * NO_LOOKUP - Try to avoid getpw/getgr routines, which can be very large
38 * NO_TAR_EXTRACT - Suppress tar extraction
39 *
40 * With all of the above macros defined (except NO_TAR_EXTRACT), you
41 * get a very small program that can recognize and extract essentially
42 * any uncompressed tar archive. On FreeBSD 5.1, this minimal program
43 * is under 64k, statically linked, which compares rather favorably to
44 * main(){printf("hello, world");}
45 * which is over 60k statically linked on the same operating system.
46 * Without any of the above macros, you get a static executable of
47 * about 180k with a lot of very sophisticated modern features.
48 * Obviously, it's trivial to add support for ISO, Zip, mtree,
49 * lzma/xz, etc. Just fill in the appropriate setup calls.
50 */
51
52 #include "minitar.h" // NOLINT(build/include)
53
54 /*
55 * NO_CREATE implies NO_BZIP2_CREATE and NO_GZIP_CREATE and NO_COMPRESS_CREATE.
56 */
57 #ifdef NO_CREATE
58 #undef NO_BZIP2_CREATE
59 #define NO_BZIP2_CREATE
60 #undef NO_COMPRESS_CREATE
61 #define NO_COMPRESS_CREATE
62 #undef NO_GZIP_CREATE
63 #define NO_GZIP_CREATE
64 #endif
65
66 /*
67 * The combination of NO_BZIP2_CREATE and NO_BZIP2_EXTRACT is
68 * equivalent to NO_BZIP2.
69 */
70 #ifdef NO_BZIP2_CREATE
71 #ifdef NO_BZIP2_EXTRACT
72 #undef NO_BZIP2
73 #define NO_BZIP2
74 #endif
75 #endif
76
77 #ifdef NO_BZIP2
78 #undef NO_BZIP2_EXTRACT
79 #define NO_BZIP2_EXTRACT
80 #undef NO_BZIP2_CREATE
81 #define NO_BZIP2_CREATE
82 #endif
83
84 /*
85 * The combination of NO_COMPRESS_CREATE and NO_COMPRESS_EXTRACT is
86 * equivalent to NO_COMPRESS.
87 */
88 #ifdef NO_COMPRESS_CREATE
89 #ifdef NO_COMPRESS_EXTRACT
90 #undef NO_COMPRESS
91 #define NO_COMPRESS
92 #endif
93 #endif
94
95 #ifdef NO_COMPRESS
96 #undef NO_COMPRESS_EXTRACT
97 #define NO_COMPRESS_EXTRACT
98 #undef NO_COMPRESS_CREATE
99 #define NO_COMPRESS_CREATE
100 #endif
101
102 /*
103 * The combination of NO_GZIP_CREATE and NO_GZIP_EXTRACT is
104 * equivalent to NO_GZIP.
105 */
106 #ifdef NO_GZIP_CREATE
107 #ifdef NO_GZIP_EXTRACT
108 #undef NO_GZIP
109 #define NO_GZIP
110 #endif
111 #endif
112
113 #ifdef NO_GZIP
114 #undef NO_GZIP_EXTRACT
115 #define NO_GZIP_EXTRACT
116 #undef NO_GZIP_CREATE
117 #define NO_GZIP_CREATE
118 #endif
119
main(int unused_argc,char * argv[])120 int main(int unused_argc, char* argv[]) {
121 const char* filename = nullptr;
122 int compress;
123 int flags;
124 int mode;
125 int opt;
126
127 mode = 'x';
128 int verbose = 0;
129 compress = '\0';
130 flags = ARCHIVE_EXTRACT_TIME;
131
132 /* Among other sins, getopt(3) pulls in printf(3). */
133 while (*++argv != nullptr && **argv == '-') {
134 const char* p = *argv + 1;
135
136 while ((opt = *p++) != '\0') {
137 switch (opt) {
138 #ifndef NO_CREATE
139 case 'c':
140 mode = opt;
141 break;
142 #endif
143 case 'f':
144 if (*p != '\0')
145 filename = p;
146 else
147 filename = *++argv;
148 p += strlen(p);
149 break;
150 #ifndef NO_BZIP2_CREATE
151 case 'j':
152 compress = opt;
153 break;
154 #endif
155 case 'p':
156 flags |= ARCHIVE_EXTRACT_PERM;
157 flags |= ARCHIVE_EXTRACT_ACL;
158 flags |= ARCHIVE_EXTRACT_FFLAGS;
159 break;
160 case 't':
161 mode = opt;
162 break;
163 case 'v':
164 verbose++;
165 break;
166 case 'x':
167 mode = opt;
168 break;
169 #ifndef NO_BZIP2_CREATE
170 case 'y':
171 compress = opt;
172 break;
173 #endif
174 #ifndef NO_COMPRESS_CREATE
175 case 'Z':
176 compress = opt;
177 break;
178 #endif
179 #ifndef NO_GZIP_CREATE
180 case 'z':
181 compress = opt;
182 break;
183 #endif
184 default:
185 usage();
186 }
187 }
188 }
189
190 switch (mode) {
191 #ifndef NO_CREATE
192 case 'c':
193 create(filename, compress, argv, verbose);
194 break;
195 #endif
196 case 't':
197 extract(filename, 0, flags, verbose);
198 break;
199 case 'x':
200 extract(filename, 1, flags, verbose);
201 break;
202 }
203
204 return (0);
205 }
206
207 // clang-format on
208