2 * This file is in the public domain.
7 * This is a compact tar extraction program whose primary goal is
8 * small size. Statically linked, it can be under 64k, depending on
9 * how cleanly factored your system libraries are. Note that this
10 * uses the standard libarchive, without any special recompilation.
11 * The only functional concession is that this program uses the
12 * uid/gid from the archive instead of doing uname/gname lookups.
13 * (Call archive_write_disk_set_standard_lookup() to enable
14 * uname/gname lookups, but be aware that this can add 500k or more to
15 * a static executable, depending on the system libraries.)
18 * gcc -static -Wall -o untar untar.c -larchive
21 * For fun, statically compile the following simple hello.c program
22 * and compare the size. (On my system, the result is 89k, untar is
26 * int main(int argc, char **argv) {
27 * printf("hello, world\n");
32 #include <sys/types.h>
33 __FBSDID("$FreeBSD$");
38 #include <archive_entry.h>
45 static void errmsg(const char *);
46 static void extract(const char *filename, int do_extract, int flags);
47 static int copy_data(struct archive *, struct archive *);
48 static void msg(const char *);
49 static void usage(void);
51 static int verbose = 0;
54 main(int argc, const char **argv)
56 const char *filename = NULL;
57 int compress, flags, mode, opt;
63 flags = ARCHIVE_EXTRACT_TIME;
65 /* Among other sins, getopt(3) pulls in printf(3). */
66 while (*++argv != NULL && **argv == '-') {
67 const char *p = *argv + 1;
69 while ((opt = *p++) != '\0') {
79 flags |= ARCHIVE_EXTRACT_PERM;
80 flags |= ARCHIVE_EXTRACT_ACL;
81 flags |= ARCHIVE_EXTRACT_FFLAGS;
100 extract(filename, 0, flags);
103 extract(filename, 1, flags);
112 extract(const char *filename, int do_extract, int flags)
116 struct archive_entry *entry;
119 a = archive_read_new();
120 ext = archive_write_disk_new();
121 archive_write_disk_set_options(ext, flags);
123 * Note: archive_write_disk_set_standard_lookup() is useful
124 * here, but it requires library routines that can add 500k or
125 * more to a static executable.
127 archive_read_support_format_tar(a);
129 * On my system, enabling other archive formats adds 20k-30k
130 * each. Enabling gzip decompression adds about 20k.
131 * Enabling bzip2 is more expensive because the libbz2 library
132 * isn't very well factored.
134 if (filename != NULL && strcmp(filename, "-") == 0)
136 if ((r = archive_read_open_file(a, filename, 10240))) {
137 errmsg(archive_error_string(a));
142 r = archive_read_next_header(a, &entry);
143 if (r == ARCHIVE_EOF)
145 if (r != ARCHIVE_OK) {
146 errmsg(archive_error_string(a));
150 if (verbose && do_extract)
152 if (verbose || !do_extract)
153 msg(archive_entry_pathname(entry));
155 r = archive_write_header(ext, entry);
157 errmsg(archive_error_string(a));
161 if (verbose || !do_extract)
164 archive_read_close(a);
165 archive_read_finish(a);
170 copy_data(struct archive *ar, struct archive *aw)
178 r = archive_read_data_block(ar, &buff, &size, &offset);
179 if (r == ARCHIVE_EOF) {
180 errmsg(archive_error_string(ar));
185 r = archive_write_data_block(aw, buff, size, offset);
186 if (r != ARCHIVE_OK) {
187 errmsg(archive_error_string(ar));
196 write(1, m, strlen(m));
200 errmsg(const char *m)
202 write(2, m, strlen(m));
208 const char *m = "Usage: untar [-tvx] [-f file] [file]\n";