diff --git a/oss-internship-2020/sapi_libarchive/CMakeLists.txt b/oss-internship-2020/sapi_libarchive/CMakeLists.txt new file mode 100644 index 0000000..2c10bfd --- /dev/null +++ b/oss-internship-2020/sapi_libarchive/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.16) + +project(libarchive_sapi CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED 17) + +# Build SAPI library +set(SAPI_ROOT "/usr/local/google/home/amedar/internship/sandboxed-api" CACHE PATH "Path to the Sandboxed API source tree") + +add_subdirectory("${SAPI_ROOT}" + "${CMAKE_BINARY_DIR}/sandboxed-api-build" + EXCLUDE_FROM_ALL +) + +add_sapi_library( + libarchive_sapi + + FUNCTIONS + archive_read_new + + INPUTS libarchive/libarchive/archive.h + LIBRARY archive + LIBRARY_NAME Libarchive + NAMESPACE "" +) + +target_include_directories(libarchive_sapi INTERFACE + "${PROJECT_BINARY_DIR}" # To find the generated SAPI header +) + + +add_subdirectory(libarchive) +add_subdirectory(examples) \ No newline at end of file diff --git a/oss-internship-2020/sapi_libarchive/ex.tar b/oss-internship-2020/sapi_libarchive/ex.tar new file mode 100644 index 0000000..60ad042 Binary files /dev/null and b/oss-internship-2020/sapi_libarchive/ex.tar differ diff --git a/oss-internship-2020/sapi_libarchive/ex2.tar b/oss-internship-2020/sapi_libarchive/ex2.tar new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/oss-internship-2020/sapi_libarchive/ex2.tar differ diff --git a/oss-internship-2020/sapi_libarchive/examples/CMakeLists.txt b/oss-internship-2020/sapi_libarchive/examples/CMakeLists.txt new file mode 100644 index 0000000..3fd0dff --- /dev/null +++ b/oss-internship-2020/sapi_libarchive/examples/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# small example - todo delete later +add_executable(small_example + small_example.cc +) + +target_link_libraries(small_example PRIVATE + archive +) + +add_executable(sapi_example + sapi_example.cc +) + +target_link_libraries(sapi_example PRIVATE + libarchive_sapi + sapi::sapi + glog::glog +) + +add_executable(untar + untar.cc +) + +target_link_libraries(untar PRIVATE + archive +) \ No newline at end of file diff --git a/oss-internship-2020/sapi_libarchive/examples/minitar.cc b/oss-internship-2020/sapi_libarchive/examples/minitar.cc new file mode 100644 index 0000000..6d956d3 --- /dev/null +++ b/oss-internship-2020/sapi_libarchive/examples/minitar.cc @@ -0,0 +1,478 @@ +/*- + * This file is in the public domain. + * Do with it as you will. + */ + +/*- + * This is a compact "tar" program whose primary goal is small size. + * Statically linked, it can be very small indeed. This serves a number + * of goals: + * o a testbed for libarchive (to check for link pollution), + * o a useful tool for space-constrained systems (boot floppies, etc), + * o a place to experiment with new implementation ideas for bsdtar, + * o a small program to demonstrate libarchive usage. + * + * Use the following macros to suppress features: + * NO_BZIP2 - Implies NO_BZIP2_CREATE and NO_BZIP2_EXTRACT + * NO_BZIP2_CREATE - Suppress bzip2 compression support. + * NO_BZIP2_EXTRACT - Suppress bzip2 auto-detection and decompression. + * NO_COMPRESS - Implies NO_COMPRESS_CREATE and NO_COMPRESS_EXTRACT + * NO_COMPRESS_CREATE - Suppress compress(1) compression support + * NO_COMPRESS_EXTRACT - Suppress compress(1) auto-detect and decompression. + * NO_CREATE - Suppress all archive creation support. + * NO_CPIO_EXTRACT - Suppress auto-detect and dearchiving of cpio archives. + * NO_GZIP - Implies NO_GZIP_CREATE and NO_GZIP_EXTRACT + * NO_GZIP_CREATE - Suppress gzip compression support. + * NO_GZIP_EXTRACT - Suppress gzip auto-detection and decompression. + * NO_LOOKUP - Try to avoid getpw/getgr routines, which can be very large + * NO_TAR_EXTRACT - Suppress tar extraction + * + * With all of the above macros defined (except NO_TAR_EXTRACT), you + * get a very small program that can recognize and extract essentially + * any uncompressed tar archive. On FreeBSD 5.1, this minimal program + * is under 64k, statically linked, which compares rather favorably to + * main(){printf("hello, world");} + * which is over 60k statically linked on the same operating system. + * Without any of the above macros, you get a static executable of + * about 180k with a lot of very sophisticated modern features. + * Obviously, it's trivial to add support for ISO, Zip, mtree, + * lzma/xz, etc. Just fill in the appropriate setup calls. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * NO_CREATE implies NO_BZIP2_CREATE and NO_GZIP_CREATE and NO_COMPRESS_CREATE. + */ +#ifdef NO_CREATE +#undef NO_BZIP2_CREATE +#define NO_BZIP2_CREATE +#undef NO_COMPRESS_CREATE +#define NO_COMPRESS_CREATE +#undef NO_GZIP_CREATE +#define NO_GZIP_CREATE +#endif + +/* + * The combination of NO_BZIP2_CREATE and NO_BZIP2_EXTRACT is + * equivalent to NO_BZIP2. + */ +#ifdef NO_BZIP2_CREATE +#ifdef NO_BZIP2_EXTRACT +#undef NO_BZIP2 +#define NO_BZIP2 +#endif +#endif + +#ifdef NO_BZIP2 +#undef NO_BZIP2_EXTRACT +#define NO_BZIP2_EXTRACT +#undef NO_BZIP2_CREATE +#define NO_BZIP2_CREATE +#endif + +/* + * The combination of NO_COMPRESS_CREATE and NO_COMPRESS_EXTRACT is + * equivalent to NO_COMPRESS. + */ +#ifdef NO_COMPRESS_CREATE +#ifdef NO_COMPRESS_EXTRACT +#undef NO_COMPRESS +#define NO_COMPRESS +#endif +#endif + +#ifdef NO_COMPRESS +#undef NO_COMPRESS_EXTRACT +#define NO_COMPRESS_EXTRACT +#undef NO_COMPRESS_CREATE +#define NO_COMPRESS_CREATE +#endif + +/* + * The combination of NO_GZIP_CREATE and NO_GZIP_EXTRACT is + * equivalent to NO_GZIP. + */ +#ifdef NO_GZIP_CREATE +#ifdef NO_GZIP_EXTRACT +#undef NO_GZIP +#define NO_GZIP +#endif +#endif + +#ifdef NO_GZIP +#undef NO_GZIP_EXTRACT +#define NO_GZIP_EXTRACT +#undef NO_GZIP_CREATE +#define NO_GZIP_CREATE +#endif + +#ifndef NO_CREATE +static void create(const char *filename, int compress, const char **argv); +#endif +static void errmsg(const char *); +static void extract(const char *filename, int do_extract, int flags); +static int copy_data(struct archive *, struct archive *); +static void msg(const char *); +static void usage(void); + +static int verbose = 0; + +int +main(int argc, const char **argv) +{ + std::cout << "BEGIN\n"; + const char *filename = NULL; + int compress, flags, mode, opt; + + (void)argc; + mode = 'x'; + verbose = 0; + compress = '\0'; + flags = ARCHIVE_EXTRACT_TIME; + + /* Among other sins, getopt(3) pulls in printf(3). */ + while (*++argv != NULL && **argv == '-') { + const char *p = *argv + 1; + + while ((opt = *p++) != '\0') { + switch (opt) { +#ifndef NO_CREATE + case 'c': + mode = opt; + break; +#endif + case 'f': + if (*p != '\0') + filename = p; + else + filename = *++argv; + p += strlen(p); + break; +#ifndef NO_BZIP2_CREATE + case 'j': + compress = opt; + break; +#endif + case 'p': + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + break; + case 't': + mode = opt; + break; + case 'v': + verbose++; + break; + case 'x': + mode = opt; + break; +#ifndef NO_BZIP2_CREATE + case 'y': + compress = opt; + break; +#endif +#ifndef NO_COMPRESS_CREATE + case 'Z': + compress = opt; + break; +#endif +#ifndef NO_GZIP_CREATE + case 'z': + compress = opt; + break; +#endif + default: + usage(); + } + } + } + + switch (mode) { +#ifndef NO_CREATE + case 'c': + create(filename, compress, argv); + break; +#endif + case 't': + extract(filename, 0, flags); + break; + case 'x': + extract(filename, 1, flags); + break; + } + + return (0); +} + + +#ifndef NO_CREATE +static char buff[16384]; + +static void +create(const char *filename, int compress, const char **argv) +{ + + std::cout << "CREATE FILENAME=" << filename << std::endl; + struct archive *a; + struct archive_entry *entry; + ssize_t len; + int fd; + + a = archive_write_new(); + switch (compress) { +#ifndef NO_BZIP2_CREATE + case 'j': case 'y': + archive_write_add_filter_bzip2(a); + break; +#endif +#ifndef NO_COMPRESS_CREATE + case 'Z': + archive_write_add_filter_compress(a); + break; +#endif +#ifndef NO_GZIP_CREATE + case 'z': + archive_write_add_filter_gzip(a); + break; +#endif + default: + archive_write_add_filter_none(a); + break; + } + archive_write_set_format_ustar(a); + if (filename != NULL && strcmp(filename, "-") == 0) + filename = NULL; + archive_write_open_filename(a, filename); + + while (*argv != NULL) { + std::cout << "handling file = " << *argv << std::endl; + struct archive *disk = archive_read_disk_new(); +#ifndef NO_LOOKUP + archive_read_disk_set_standard_lookup(disk); +#endif + int r; + + r = archive_read_disk_open(disk, *argv); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(disk)); + errmsg("\n"); + exit(1); + } + + for (;;) { + int needcr = 0; + + entry = archive_entry_new(); + r = archive_read_next_header2(disk, entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(disk)); + errmsg("\n"); + exit(1); + } + archive_read_disk_descend(disk); + if (verbose) { + msg("a "); + msg(archive_entry_pathname(entry)); + needcr = 1; + } + r = archive_write_header(a, entry); + if (r < ARCHIVE_OK) { + std::cout << " --- error here, code = " << r << " --- " << std::endl; + errmsg(": "); + errmsg(archive_error_string(a)); + needcr = 1; + } + if (r == ARCHIVE_FATAL) + exit(1); + if (r > ARCHIVE_FAILED) { +#if 0 + /* Ideally, we would be able to use + * the same code to copy a body from + * an archive_read_disk to an + * archive_write that we use for + * copying data from an archive_read + * to an archive_write_disk. + * Unfortunately, this doesn't quite + * work yet. */ + copy_data(disk, a); +#else + /* For now, we use a simpler loop to copy data + * into the target archive. */ + fd = open(archive_entry_sourcepath(entry), O_RDONLY); + len = read(fd, buff, sizeof(buff)); + while (len > 0) { + archive_write_data(a, buff, len); + len = read(fd, buff, sizeof(buff)); + } + close(fd); +#endif + } + archive_entry_free(entry); + if (needcr) + msg("\n"); + } + archive_read_close(disk); + archive_read_free(disk); + argv++; + } + archive_write_close(a); + archive_write_free(a); +} +#endif + +static void +extract(const char *filename, int do_extract, int flags) +{ + + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int r; + + a = archive_read_new(); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); +#ifndef NO_BZIP2_EXTRACT + archive_read_support_filter_bzip2(a); +#endif +#ifndef NO_GZIP_EXTRACT + archive_read_support_filter_gzip(a); +#endif +#ifndef NO_COMPRESS_EXTRACT + archive_read_support_filter_compress(a); +#endif +#ifndef NO_TAR_EXTRACT + archive_read_support_format_tar(a); +#endif +#ifndef NO_CPIO_EXTRACT + archive_read_support_format_cpio(a); +#endif +#ifndef NO_LOOKUP + archive_write_disk_set_standard_lookup(ext); +#endif + if (filename != NULL && strcmp(filename, "-") == 0) + filename = NULL; + if ((r = archive_read_open_filename(a, filename, 10240))) { + errmsg(archive_error_string(a)); + errmsg("\n"); + exit(r); + } + for (;;) { + int needcr = 0; + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(a)); + errmsg("\n"); + exit(1); + } + if (verbose && do_extract) + msg("x "); + if (verbose || !do_extract) { + msg(archive_entry_pathname(entry)); + msg(" "); + needcr = 1; + } + if (do_extract) { + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(a)); + needcr = 1; + } + else { + r = copy_data(a, ext); + if (r != ARCHIVE_OK) + needcr = 1; + } + } + if (needcr) + msg("\n"); + } + archive_read_close(a); + archive_read_free(a); + + archive_write_close(ext); + archive_write_free(ext); + exit(0); +} + +static int +copy_data(struct archive *ar, struct archive *aw) +{ + int r; + const void *buff; + size_t size; + int64_t offset; + + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(ar)); + return (r); + } + r = archive_write_data_block(aw, buff, size, offset); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(ar)); + return (r); + } + } +} + +static void +msg(const char *m) +{ + write(1, m, strlen(m)); +} + +static void +errmsg(const char *m) +{ + if (m == NULL) { + m = "Error: No error description provided.\n"; + } + write(2, m, strlen(m)); +} + +static void +usage(void) +{ +/* Many program options depend on compile options. */ + const char *m = "Usage: minitar [-" +#ifndef NO_CREATE + "c" +#endif +#ifndef NO_BZIP2 + "j" +#endif + "tvx" +#ifndef NO_BZIP2 + "y" +#endif +#ifndef NO_COMPRESS + "Z" +#endif +#ifndef NO_GZIP + "z" +#endif + "] [-f file] [file]\n"; + + errmsg(m); + exit(1); +} diff --git a/oss-internship-2020/sapi_libarchive/examples/sapi_example.cc b/oss-internship-2020/sapi_libarchive/examples/sapi_example.cc new file mode 100644 index 0000000..7cc638e --- /dev/null +++ b/oss-internship-2020/sapi_libarchive/examples/sapi_example.cc @@ -0,0 +1,8 @@ +#include +#include "libarchive_sapi.sapi.h" + + +int main() { + std::cout << "WORKS2" << std::endl; + return 0; +} \ No newline at end of file diff --git a/oss-internship-2020/sapi_libarchive/examples/small_example.cc b/oss-internship-2020/sapi_libarchive/examples/small_example.cc new file mode 100644 index 0000000..55641a5 --- /dev/null +++ b/oss-internship-2020/sapi_libarchive/examples/small_example.cc @@ -0,0 +1,9 @@ +#include + +#include +#include + +int main() { + std::cout << "WORKS" << std::endl; + return 0; +} \ No newline at end of file diff --git a/oss-internship-2020/sapi_libarchive/examples/tarfilter.cc b/oss-internship-2020/sapi_libarchive/examples/tarfilter.cc new file mode 100644 index 0000000..0d323e1 --- /dev/null +++ b/oss-internship-2020/sapi_libarchive/examples/tarfilter.cc @@ -0,0 +1,113 @@ +/* + * This file is in the public domain. + * + * Feel free to use it as you wish. + */ + +/* + * This example program reads an archive from stdin (which can be in + * any format recognized by libarchive) and writes certain entries to + * an uncompressed ustar archive on stdout. This is a template for + * many kinds of archive manipulation: converting formats, resetting + * ownership, inserting entries, removing entries, etc. + * + * To compile: + * gcc -Wall -o tarfilter tarfilter.c -larchive -lz -lbz2 + */ + +#include +#include +#include +#include +#include +#include + +static void +die(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + char buff[8192]; + ssize_t len; + int r; + mode_t m; + struct archive *ina; + struct archive *outa; + struct archive_entry *entry; + + /* Read an archive from stdin, with automatic format detection. */ + ina = archive_read_new(); + if (ina == NULL) + die("Couldn't create archive reader."); + if (archive_read_support_filter_all(ina) != ARCHIVE_OK) + die("Couldn't enable decompression"); + if (archive_read_support_format_all(ina) != ARCHIVE_OK) + die("Couldn't enable read formats"); + if (archive_read_open_fd(ina, 0, 10240) != ARCHIVE_OK) + die("Couldn't open input archive"); + + /* Write an uncompressed ustar archive to stdout. */ + outa = archive_write_new(); + if (outa == NULL) + die("Couldn't create archive writer."); + if (archive_write_set_compression_none(outa) != ARCHIVE_OK) + die("Couldn't enable compression"); + if (archive_write_set_format_ustar(outa) != ARCHIVE_OK) + die("Couldn't set output format"); + if (archive_write_open_fd(outa, 1) != ARCHIVE_OK) + die("Couldn't open output archive"); + + /* Examine each entry in the input archive. */ + while ((r = archive_read_next_header(ina, &entry)) == ARCHIVE_OK) { + fprintf(stderr, "%s: ", archive_entry_pathname(entry)); + + /* Skip anything that isn't a regular file. */ + if (!S_ISREG(archive_entry_mode(entry))) { + fprintf(stderr, "skipped\n"); + continue; + } + + /* Make everything owned by root/wheel. */ + archive_entry_set_uid(entry, 0); + archive_entry_set_uname(entry, "root"); + archive_entry_set_gid(entry, 0); + archive_entry_set_gname(entry, "wheel"); + + /* Make everything permission 0744, strip SUID, etc. */ + m = archive_entry_mode(entry); + archive_entry_set_mode(entry, (m & ~07777) | 0744); + + /* Copy input entries to output archive. */ + if (archive_write_header(outa, entry) != ARCHIVE_OK) + die("Error writing output archive"); + if (archive_entry_size(entry) > 0) { + len = archive_read_data(ina, buff, sizeof(buff)); + while (len > 0) { + if (archive_write_data(outa, buff, len) != len) + die("Error writing output archive"); + len = archive_read_data(ina, buff, sizeof(buff)); + } + if (len < 0) + die("Error reading input archive"); + } + fprintf(stderr, "copied\n"); + } + if (r != ARCHIVE_EOF) + die("Error reading archive"); + /* Close the archives. */ + if (archive_read_free(ina) != ARCHIVE_OK) + die("Error closing input archive"); + if (archive_write_free(outa) != ARCHIVE_OK) + die("Error closing output archive"); + return (0); +} diff --git a/oss-internship-2020/sapi_libarchive/examples/untar.cc b/oss-internship-2020/sapi_libarchive/examples/untar.cc new file mode 100644 index 0000000..7f06c5b --- /dev/null +++ b/oss-internship-2020/sapi_libarchive/examples/untar.cc @@ -0,0 +1,277 @@ +/* + * This file is in the public domain. + * Use it as you wish. + */ + +/* + * This is a compact tar extraction program using libarchive whose + * primary goal is small executable size. Statically linked, it can + * be very small, depending in large part on how cleanly factored your + * system libraries are. Note that this uses the standard libarchive, + * without any special recompilation. The only functional concession + * is that this program uses the uid/gid from the archive instead of + * doing uname/gname lookups. (Add a call to + * archive_write_disk_set_standard_lookup() to enable uname/gname + * lookups, but be aware that this can add 500k or more to a static + * executable, depending on the system libraries, since user/group + * lookups frequently pull in password, YP/LDAP, networking, and DNS + * resolver libraries.) + * + * To build: + * $ gcc -static -Wall -o untar untar.c -larchive + * $ strip untar + * + * NOTE: On some systems, you may need to add additional flags + * to ensure that untar.c is compiled the same way as libarchive + * was compiled. In particular, Linux users will probably + * have to add -D_FILE_OFFSET_BITS=64 to the command line above. + * + * For fun, statically compile the following simple hello.c program + * using the same flags as for untar and compare the size: + * + * #include + * int main(int argc, char **argv) { + * printf("hello, world\n"); + * return(0); + * } + * + * You may be even more surprised by the compiled size of true.c listed here: + * + * int main(int argc, char **argv) { + * return (0); + * } + * + * On a slightly customized FreeBSD 5 system that I used around + * 2005, hello above compiled to 89k compared to untar of 69k. So at + * that time, libarchive's tar reader and extract-to-disk routines + * compiled to less code than printf(). + * + * On my FreeBSD development system today (August, 2009): + * hello: 195024 bytes + * true: 194912 bytes + * untar: 259924 bytes + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +static void errmsg(const char *); +static void extract(const char *filename, int do_extract, int flags); +static void fail(const char *, const char *, int); +static int copy_data(struct archive *, struct archive *); +static void msg(const char *); +static void usage(void); +static void warn(const char *, const char *); + +static int verbose = 0; + +int +main(int argc, const char **argv) +{ + const char *filename = NULL; + int compress, flags, mode, opt; + + (void)argc; + mode = 'x'; + verbose = 0; + compress = '\0'; + flags = ARCHIVE_EXTRACT_TIME; + + /* Among other sins, getopt(3) pulls in printf(3). */ + while (*++argv != NULL && **argv == '-') { + const char *p = *argv + 1; + + while ((opt = *p++) != '\0') { + switch (opt) { + case 'f': + if (*p != '\0') + filename = p; + else + filename = *++argv; + p += strlen(p); + break; + case 'p': + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + break; + case 't': + mode = opt; + break; + case 'v': + verbose++; + break; + case 'x': + mode = opt; + break; + default: + usage(); + } + } + } + + std::cout << "begin\n"; + + switch (mode) { + case 't': + extract(filename, 0, flags); + break; + case 'x': + extract(filename, 1, flags); + break; + } + + std::cout << "end"; + + return (0); +} + + +static void +extract(const char *filename, int do_extract, int flags) +{ + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int r; + + a = archive_read_new(); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); + /* + * Note: archive_write_disk_set_standard_lookup() is useful + * here, but it requires library routines that can add 500k or + * more to a static executable. + */ + archive_read_support_format_tar(a); + /* + * On my system, enabling other archive formats adds 20k-30k + * each. Enabling gzip decompression adds about 20k. + * Enabling bzip2 is more expensive because the libbz2 library + * isn't very well factored. + */ + + std::cout <<"AAA\n"; + if (filename != NULL && strcmp(filename, "-") == 0) + filename = NULL; + if ((r = archive_read_open_filename(a, filename, 10240))) + fail("archive_read_open_filename()", + archive_error_string(a), r); + + std::cout << "BBB\n"; + for (;;) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) + fail("archive_read_next_header()", + archive_error_string(a), 1); + if (verbose && do_extract) + msg("x "); + if (verbose || !do_extract) + msg(archive_entry_pathname(entry)); + if (do_extract) { + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) + warn("archive_write_header()", + archive_error_string(ext)); + else { + copy_data(a, ext); + r = archive_write_finish_entry(ext); + if (r != ARCHIVE_OK) + fail("archive_write_finish_entry()", + archive_error_string(ext), 1); + } + + } + if (verbose || !do_extract) + msg("\n"); + } + archive_read_close(a); + archive_read_free(a); + + archive_write_close(ext); + archive_write_free(ext); + exit(0); +} + +static int +copy_data(struct archive *ar, struct archive *aw) +{ + int r; + const void *buff; + size_t size; +#if ARCHIVE_VERSION_NUMBER >= 3000000 + int64_t offset; +#else + off_t offset; +#endif + + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r != ARCHIVE_OK) + return (r); + r = archive_write_data_block(aw, buff, size, offset); + if (r != ARCHIVE_OK) { + warn("archive_write_data_block()", + archive_error_string(aw)); + return (r); + } + } +} + +/* + * These reporting functions use low-level I/O; on some systems, this + * is a significant code reduction. Of course, on many server and + * desktop operating systems, malloc() and even crt rely on printf(), + * which in turn pulls in most of the rest of stdio, so this is not an + * optimization at all there. (If you're going to pay 100k or more + * for printf() anyway, you may as well use it!) + */ +static void +msg(const char *m) +{ + write(1, m, strlen(m)); +} + +static void +errmsg(const char *m) +{ + write(2, m, strlen(m)); +} + +static void +warn(const char *f, const char *m) +{ + errmsg(f); + errmsg(" failed: "); + errmsg(m); + errmsg("\n"); +} + +static void +fail(const char *f, const char *m, int r) +{ + warn(f, m); + exit(r); +} + +static void +usage(void) +{ + const char *m = "Usage: untar [-tvx] [-f file] [file]\n"; + errmsg(m); + exit(1); +} diff --git a/oss-internship-2020/sapi_libarchive/normal.tar b/oss-internship-2020/sapi_libarchive/normal.tar new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/oss-internship-2020/sapi_libarchive/normal.tar differ