mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
added some more examples
This commit is contained in:
parent
ab8d8cb1b4
commit
a6e0bb6e5b
48
oss-internship-2020/sapi_libarchive/CMakeLists.txt
Normal file
48
oss-internship-2020/sapi_libarchive/CMakeLists.txt
Normal file
|
@ -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)
|
BIN
oss-internship-2020/sapi_libarchive/ex.tar
Normal file
BIN
oss-internship-2020/sapi_libarchive/ex.tar
Normal file
Binary file not shown.
BIN
oss-internship-2020/sapi_libarchive/ex2.tar
Normal file
BIN
oss-internship-2020/sapi_libarchive/ex2.tar
Normal file
Binary file not shown.
40
oss-internship-2020/sapi_libarchive/examples/CMakeLists.txt
Normal file
40
oss-internship-2020/sapi_libarchive/examples/CMakeLists.txt
Normal file
|
@ -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
|
||||
)
|
478
oss-internship-2020/sapi_libarchive/examples/minitar.cc
Normal file
478
oss-internship-2020/sapi_libarchive/examples/minitar.cc
Normal file
|
@ -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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#include <iostream>
|
||||
#include "libarchive_sapi.sapi.h"
|
||||
|
||||
|
||||
int main() {
|
||||
std::cout << "WORKS2" << std::endl;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
|
||||
int main() {
|
||||
std::cout << "WORKS" << std::endl;
|
||||
return 0;
|
||||
}
|
113
oss-internship-2020/sapi_libarchive/examples/tarfilter.cc
Normal file
113
oss-internship-2020/sapi_libarchive/examples/tarfilter.cc
Normal file
|
@ -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 <sys/stat.h>
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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);
|
||||
}
|
277
oss-internship-2020/sapi_libarchive/examples/untar.cc
Normal file
277
oss-internship-2020/sapi_libarchive/examples/untar.cc
Normal file
|
@ -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 <stdio.h>
|
||||
* 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 <iostream>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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);
|
||||
}
|
BIN
oss-internship-2020/sapi_libarchive/normal.tar
Normal file
BIN
oss-internship-2020/sapi_libarchive/normal.tar
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user