Merge code from upstream libtar + bug fixes
All updates and fixes applied from upstream libtar as of March 1, 2016. Debug flag is disabled, however non-debug output now provides 1 line of useful output per object extracted. I've also merged some fixes from CyanogenMod's fork of libtar: From: Tom Marshall <tdm@cyngn.com> Date: Thu, 11 Feb 2016 16:24:40 -0800 Subject: libtar: Cleanup, secure, and extend numeric fields Commit: e18b457ea1cbf6be1adc3b75450ed1c737cd82ea From: Tom Marshall <tdm@cyngn.com> Date: Thu, 11 Feb 2016 12:49:30 -0800 Subject: libtar: Make file sizes 64-bit clean Commit: e628c2025549a24018bc568351465130a05daafb From: Tom Marshall <tdm@cyngn.com> Date: Thu, 17 Apr 2014 09:39:25 -0700 Subject: libtar: Add methods for in-memory files Commit: 8ec5627a8ff0a91724c6d5b344f0e887da922527 From: Tom Marshall <tdm@cyngn.com> Date: Wed, 2 Jul 2014 09:34:40 -0700 Subject: libtar: Fix hardlink extract Commit: 166d83a51e0c51abcea37694dbd7df92d03c1f56 From: philz-cwm6 <phytowardt@gmail.com> Date: Sat, 26 Apr 2014 01:11:35 +0200 Subject: libtar: Various bug fixes and enhancements Commit: a271d763e94235ccee9ecaabdb52bf4b9b2f8c06 (Some of this was not merged in, as better solutions were available from upstream libtar) From: Tom Marshall <tdm@cyngn.com> Date: Wed, 9 Apr 2014 09:35:54 -0700 Subject: libtar: Add const qualifiers to reduce compile warnings Commit: 0600afa19fe827d06d3fcf24a7aabd52dbf487b4 Change-Id: I6d008cb6fdf950f835bbed63aeb8727cc5c86083
This commit is contained in:
committed by
Ethan Yonker
parent
64ffe730a6
commit
6f57f7c601
+331
-11
@@ -1,15 +1,335 @@
|
||||
2002-12-09 added list_empty() and hash_empty() functions
|
||||
NOTE:
|
||||
All releases below marked (Chris Frey) are maintenance releases
|
||||
done by Chris Frey, temporarily stepping in for Mark Roth.
|
||||
These releases are git-based only and can be found at:
|
||||
http://repo.or.cz/w/libtar.git
|
||||
|
||||
2002-09-12 fixed list_iterate function to return -1 if it gets
|
||||
an invalid argument
|
||||
Both git downloads and tarball downloads are possible at this site.
|
||||
|
||||
include <config.h> and <compat.h> from source files, not
|
||||
from header file, since header file is sometimes
|
||||
installed as part of a user-visible API
|
||||
(those APIs should eventually be redesigned without the
|
||||
listhash code being publicly visible, but for now we
|
||||
need to accomodate this)
|
||||
|
||||
2002-07-07 modified list iterate function to return int
|
||||
(returns -1 if plugin function returns -1)
|
||||
libtar 1.2.20 - 2013/10/09 (Chris Frey)
|
||||
-------------
|
||||
Added extern "C" protectors to listhash.h
|
||||
Added autoconf checks for __thread compiler support
|
||||
Fixed size_t overflow bug, as reported by Timo Warns
|
||||
Fixed thread-safe bug in th_get_pathname() (Sergey Zhitomirsky)
|
||||
|
||||
|
||||
libtar 1.2.19 - 2012/12/11 (Chris Frey)
|
||||
-------------
|
||||
Removed varargs.h and all dependencies, to avoid user compile errors
|
||||
|
||||
Fixed some short int / int compiler warnings in va_arg() usage
|
||||
|
||||
Fixed some gcc built-in compiler warnings
|
||||
|
||||
Changed autoconf support code from AC_RUN_ to AC_COMPILE_ to fix
|
||||
issues reported during cross-compiling.
|
||||
|
||||
Applied most of Jan Cermak's const char* function argument patch.
|
||||
|
||||
|
||||
libtar 1.2.18 - 2012/08/02 (Chris Frey)
|
||||
-------------
|
||||
Added more forgiving CRC checking logic when reading tar files
|
||||
|
||||
Note: If your application uses the macro th_crc_ok(), then to gain full
|
||||
advantage of the changes in this version, you will need to recompile
|
||||
your application against the new headers. Otherwise, the library is
|
||||
drop-in replaceable, as usual.
|
||||
|
||||
|
||||
libtar 1.2.17 - 2012/07/24 (Chris Frey)
|
||||
-------------
|
||||
Applied Tim Band's checksum patch from mailing list (thanks!)
|
||||
|
||||
|
||||
libtar 1.2.16 - 2012/05/17 (Chris Frey)
|
||||
-------------
|
||||
Fixed build system to allow for out-of-source tree builds
|
||||
|
||||
|
||||
libtar 1.2.15 - 2012/05/10 (Chris Frey)
|
||||
-------------
|
||||
Chris Frey (1):
|
||||
Fixed harmless buffer overflow which is caught by FORTIFY on some systems
|
||||
|
||||
|
||||
libtar 1.2.14 - 2011/12/22 (Chris Frey)
|
||||
-------------
|
||||
Chris Frey (1):
|
||||
Fixed truncation check, so 100 char names get GNU extension support when enabled
|
||||
|
||||
|
||||
libtar 1.2.13 - 2011/06/13 (Chris Frey)
|
||||
-------------
|
||||
Chris Frey (10):
|
||||
Fixed incorrect URL in readme
|
||||
Added autoconf/ as macro dir
|
||||
Added autogen.sh script to build a fresh configure
|
||||
Renamed autoconf/aclocal.m4 to psg.m4 so aclocal isn't so confused
|
||||
Removed m4 includes, and straightened out [] m4 quoting for modern autoconfs
|
||||
Removed auto-generated files
|
||||
Added datarootdir to Makefile.in's
|
||||
Fixed header warnings
|
||||
Applied Marcin Gibula's patch fixing tar_extract_glob()
|
||||
Changed root Makefile.in to Makefile.am, which make autoreconf workable
|
||||
|
||||
Glenn McGrath (1):
|
||||
Use libtool to build dynamic library
|
||||
|
||||
James Morrison (1):
|
||||
Document stupidity of tartype_t in libtar.c.
|
||||
|
||||
Magnus Holmgren (1):
|
||||
Escape hyphens that should be minus signs in man pages.
|
||||
|
||||
Per Lidén (2):
|
||||
Fix memory leak in th_get_pathname
|
||||
Reduce memory used by libtar when extracting files.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.11 - 3/2/03
|
||||
-------------
|
||||
|
||||
- updated autoconf macros, compat code, and listhash code
|
||||
- fixed tar_extract_regfile() to pass mode argument to open()
|
||||
(caused EPERM on Solaris NFS clients)
|
||||
- updated README
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.10 - 12/15/02
|
||||
-------------
|
||||
|
||||
- updated README
|
||||
- minor Makefile fixes
|
||||
- fixed TH_ISREG() macro to not return true for hard links
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.9 - 11/19/02
|
||||
------------
|
||||
|
||||
- fixed th_read() to return 1 on EOF
|
||||
(thanks to Yves Crespin <Crespin.Quartz@WANADOO.FR> for the bug report)
|
||||
- minor portability fixes
|
||||
(thanks to Yves Crespin <Crespin.Quartz@WANADOO.FR> for the bug report)
|
||||
- fixed segfault on extracting filenames with 8-bit ASCII characters
|
||||
(thanks to Per Liden <per@FUKT.BTH.SE> for the patch)
|
||||
- fixed TH_ISDIR() macro and th_get_mode() function to handle old
|
||||
archives that don't set the typeflag field right for directories
|
||||
- use 0777 instead of 0755 in mkdirhier()
|
||||
(thanks to Yves Crespin <Crespin.Quartz@WANADOO.FR> for the bug report)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.8 - 9/13/02
|
||||
------------
|
||||
|
||||
- added "-I../listhash" to CPPFLAGS in libtar/Makefile.in
|
||||
(thanks to Kris Warkentin <kewarken@QNX.COM> for the bug report)
|
||||
- added .PHONY target to Makefile.in
|
||||
(thanks to Steven Engelhardt <sengelha@YAHOO.COM> for the bug report)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.7 - 9/12/02
|
||||
------------
|
||||
|
||||
- fixed minor bugs in listhash code
|
||||
(thanks to Jim Knoble <jmknoble@pobox.com> for the bug reports)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.6 - 9/10/02
|
||||
------------
|
||||
|
||||
- updated COPYRIGHT file
|
||||
- do not check magic field by default
|
||||
(replaced TAR_IGNORE_MAGIC option with TAR_CHECK_MAGIC to enable check)
|
||||
- fixed th_get_mode() not to modify S_IFMT bits if they were already set
|
||||
- fixed TH_IS*() macros to check the S_IFMT mode bits in addition to typeflag
|
||||
(this allows us to handle old tar archives that set mode bits but not
|
||||
typeflag field for directories and other special files)
|
||||
- updated to autoconf-2.53
|
||||
- restructured autoconf macros
|
||||
- added "b" to gzoflags in gzopen_frontend() for win32 compatibility
|
||||
(thanks to Kris Eric Warkentin <kewarken@QNX.COM> for reporting this)
|
||||
- if O_BINARY is defined (as on win32), set that bit in oflags in tar_open()
|
||||
(thanks to Kris Eric Warkentin <kewarken@QNX.COM> for reporting this)
|
||||
- also use O_BINARY in when calling open() from tar_extract_regfile()
|
||||
(based on patch from Graeme Peterson <gp@qnx.com>)
|
||||
- added COMPAT_FUNC_MAKEDEV macro to handle 3-arg version of makedev()
|
||||
(based on patch from Graeme Peterson <gp@qnx.com>)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.5 - 2/20/02
|
||||
------------
|
||||
|
||||
- updated to autoconf-2.52
|
||||
- improved Makefile portability
|
||||
- fixed memory leak in hard-link detection code
|
||||
(thanks to Michael Kamp <kamp@HITT.NL> for the bug report)
|
||||
- fixed memory leak in symlink handling code
|
||||
(thanks to Michael Kamp <kamp@HITT.NL> for the bug report)
|
||||
- fixed memory leak in GNU long filename code
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.4 - 7/24/01
|
||||
------------
|
||||
|
||||
- code cleanups to make gcc -Wall happy
|
||||
(thanks to Jim Knoble <jmknoble@POBOX.COM> for the patch)
|
||||
- call utime() before chmod() in tar_set_file_perms() for cygwin
|
||||
(thanks to Kris Eric Warkentin <kewarken@QNX.COM> for reporting this)
|
||||
- added "-g" flag to trigger GNU extensions in libtar binary
|
||||
- fixed buffer termination bugs in POSIX filename prefix encoding
|
||||
(thanks to Joerg Schilling <schilling@fokus.gmd.de> for reporting this)
|
||||
- fixed bug in th_crc_calc() for filenames with 8-bit ASCII characters
|
||||
(thanks to Hamdouni El Bachir <bach@zehc.net> for reporting the bug
|
||||
and Antoniu-George SAVU <santoniu@libertysurf.fr> for the patch)
|
||||
- fixed backwards conditional expression in th_read()
|
||||
(thanks to Antoniu-George SAVU <santoniu@LIBERTYSURF.FR> for the patch)
|
||||
- added new tar_open() options to replace compile-time settings:
|
||||
TAR_IGNORE_EOT, TAR_IGNORE_MAGIC, TAR_CHECK_VERSION, TAR_IGNORE_CRC
|
||||
(based on feedback from Kris Eric Warkentin <kewarken@QNX.COM>)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.3 - 6/26/01
|
||||
------------
|
||||
|
||||
- misc portability fixes for OpenBSD
|
||||
- fixed libtar.h to work with C++ programs
|
||||
- fixed tar_extract_file() to properly check for pre-existing symlinks
|
||||
(based on patch from Per Lid?n <per@fukt.hk-r.se>)
|
||||
- fixed hash creation in tar_init()
|
||||
- replaced mkdirhier() with non-recursive version
|
||||
- updated autoconf macros, compat code, and listhash code
|
||||
- reformatted code for readability
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.2 - 1/12/01
|
||||
------------
|
||||
|
||||
- fixed th_print_long_ls() to not truncate user and group names
|
||||
- code cleanups to make -Wall happy
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2.1 - 1/8/01
|
||||
------------
|
||||
|
||||
- updated WSG_ENCAP autoconf macro
|
||||
- fixed autoconf macros to behave properly when a config.cache file
|
||||
is present
|
||||
- fixed doc/Makefile.in to create links during compilation, not
|
||||
installation
|
||||
- fixed listhash manpage .so link lists
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.2 - 1/4/01
|
||||
----------
|
||||
|
||||
- minor code cleanups
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b8 - 1/2/01
|
||||
-------------
|
||||
|
||||
- updated WSG_ENCAP autoconf macro
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b7 - 12/13/00
|
||||
-------------
|
||||
|
||||
- fixed autoconf snprintf() test to make sure it NUL-terminates
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b6 - 11/30/00
|
||||
-------------
|
||||
|
||||
- added $(DESTDIR) to Makefiles
|
||||
- Makefile changes to support WSG_PKG and WSG_ENCAP autoconf macros
|
||||
- changed lib/output.c to use strftime() where available
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b5 - 10/29/00
|
||||
-------------
|
||||
|
||||
- Makefile fix
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b4 - 10/29/00
|
||||
-------------
|
||||
|
||||
- more directory reorganization
|
||||
- minor Makefile cleanups
|
||||
- minor portability fixes
|
||||
- added function typecasting to avoid compiler warnings
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b3 - 10/26/00
|
||||
-------------
|
||||
|
||||
- updated aclocal.m4
|
||||
- updated README
|
||||
- updated manpages
|
||||
- minor directory structure changes because of CVS setup
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b2 - 10/5/00
|
||||
-------------
|
||||
|
||||
- added --without-zlib configure option
|
||||
- minor portability fixes
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b1 - 8/21/00
|
||||
-------------
|
||||
|
||||
- API changes:
|
||||
- implemented tar_fdopen()
|
||||
- implemented tar_fd()
|
||||
- added TAR **t argument to tar_open() instead of returning dynamic memory
|
||||
- if TAR_NOOVERWRITE is set in options and O_CREAT is set in oflags,
|
||||
tar_open() automatically sets O_EXCL as well
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
libtar 1.1.b0 - 7/10/00
|
||||
-------------
|
||||
|
||||
- API changes:
|
||||
- replaced internal table of tar file types with a tartype_t passed to
|
||||
tar_open() by the caller
|
||||
(allows file access methods to be defined dynamically)
|
||||
- fixed tar_append_tree() to grok normal files as well as directories
|
||||
- replaced mk_dirs_for_file() with mkdirhier() from epkg
|
||||
- replaced strtok_r() with strsep()
|
||||
- updated list/hash code to new interface
|
||||
|
||||
- autoconf changes:
|
||||
- added aclocal.m4 to clean up configure.in
|
||||
- minor portability fixes related to lib/fnmatch.c
|
||||
|
||||
- fixed a bug in tar_open() where the result of open() was being
|
||||
checked for 0 instead of -1 to detect error
|
||||
|
||||
- updated libtar driver program to handle both .tar.gz and ordinary .tar
|
||||
via the -z option
|
||||
|
||||
|
||||
+95
-21
@@ -13,8 +13,11 @@
|
||||
#include <internal.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -28,7 +31,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
#include "selinux/selinux.h"
|
||||
# include "selinux/selinux.h"
|
||||
#endif
|
||||
|
||||
struct tar_dev
|
||||
@@ -57,7 +60,7 @@ tar_dev_free(tar_dev_t *tdp)
|
||||
|
||||
/* appends a file to the tar archive */
|
||||
int
|
||||
tar_append_file(TAR *t, char *realname, char *savename)
|
||||
tar_append_file(TAR *t, const char *realname, const char *savename)
|
||||
{
|
||||
struct stat s;
|
||||
int i;
|
||||
@@ -82,38 +85,46 @@ tar_append_file(TAR *t, char *realname, char *savename)
|
||||
|
||||
/* set header block */
|
||||
#ifdef DEBUG
|
||||
puts(" tar_append_file(): setting header block...");
|
||||
puts("tar_append_file(): setting header block...");
|
||||
#endif
|
||||
memset(&(t->th_buf), 0, sizeof(struct tar_header));
|
||||
th_set_from_stat(t, &s);
|
||||
|
||||
/* set the header path */
|
||||
#ifdef DEBUG
|
||||
puts(" tar_append_file(): setting header path...");
|
||||
puts("tar_append_file(): setting header path...");
|
||||
#endif
|
||||
th_set_path(t, (savename ? savename : realname));
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
/* get selinux context */
|
||||
if(t->options & TAR_STORE_SELINUX) {
|
||||
if(t->th_buf.selinux_context != NULL) {
|
||||
if (t->options & TAR_STORE_SELINUX)
|
||||
{
|
||||
if (t->th_buf.selinux_context != NULL)
|
||||
{
|
||||
free(t->th_buf.selinux_context);
|
||||
t->th_buf.selinux_context = NULL;
|
||||
}
|
||||
|
||||
security_context_t selinux_context = NULL;
|
||||
if (lgetfilecon(realname, &selinux_context) >= 0) {
|
||||
if (lgetfilecon(realname, &selinux_context) >= 0)
|
||||
{
|
||||
t->th_buf.selinux_context = strdup(selinux_context);
|
||||
printf("setting selinux context: %s\n", selinux_context);
|
||||
printf(" ==> set selinux context: %s\n", selinux_context);
|
||||
freecon(selinux_context);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("Failed to get selinux context");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if it's a hardlink */
|
||||
#ifdef DEBUG
|
||||
puts(" tar_append_file(): checking inode cache for hardlink...");
|
||||
puts("tar_append_file(): checking inode cache for hardlink...");
|
||||
#endif
|
||||
libtar_hashptr_reset(&hp);
|
||||
if (libtar_hash_getkey(t->h, &hp, &(s.st_dev),
|
||||
@@ -171,7 +182,7 @@ tar_append_file(TAR *t, char *realname, char *savename)
|
||||
i = MAXPATHLEN - 1;
|
||||
path[i] = '\0';
|
||||
#ifdef DEBUG
|
||||
printf(" tar_append_file(): encoding symlink \"%s\" -> "
|
||||
printf("tar_append_file(): encoding symlink \"%s\" -> "
|
||||
"\"%s\"...\n", realname, path);
|
||||
#endif
|
||||
th_set_link(t, path);
|
||||
@@ -179,10 +190,10 @@ tar_append_file(TAR *t, char *realname, char *savename)
|
||||
|
||||
/* print file info */
|
||||
if (t->options & TAR_VERBOSE)
|
||||
th_print_long_ls(t);
|
||||
printf("%s\n", th_get_pathname(t));
|
||||
|
||||
#ifdef DEBUG
|
||||
puts(" tar_append_file(): writing header");
|
||||
puts("tar_append_file(): writing header");
|
||||
#endif
|
||||
/* write header */
|
||||
if (th_write(t) != 0)
|
||||
@@ -193,7 +204,7 @@ tar_append_file(TAR *t, char *realname, char *savename)
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
puts(" tar_append_file(): back from th_write()");
|
||||
puts("tar_append_file(): back from th_write()");
|
||||
#endif
|
||||
|
||||
/* if it's a regular file, write the contents as well */
|
||||
@@ -229,14 +240,19 @@ tar_append_eof(TAR *t)
|
||||
|
||||
/* add file contents to a tarchive */
|
||||
int
|
||||
tar_append_regfile(TAR *t, char *realname)
|
||||
tar_append_regfile(TAR *t, const char *realname)
|
||||
{
|
||||
char block[T_BLOCKSIZE];
|
||||
int filefd;
|
||||
int j;
|
||||
size_t size, i;
|
||||
int64_t i, size;
|
||||
ssize_t j;
|
||||
int rv = -1;
|
||||
|
||||
#if defined(O_BINARY)
|
||||
filefd = open(realname, O_RDONLY|O_BINARY);
|
||||
#else
|
||||
filefd = open(realname, O_RDONLY);
|
||||
#endif
|
||||
if (filefd == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -253,25 +269,83 @@ tar_append_regfile(TAR *t, char *realname)
|
||||
{
|
||||
if (j != -1)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
if (tar_block_write(t, &block) == -1)
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
j = read(filefd, &block, i);
|
||||
if (j == -1)
|
||||
goto fail;
|
||||
memset(&(block[i]), 0, T_BLOCKSIZE - i);
|
||||
if (tar_block_write(t, &block) == -1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* success! */
|
||||
rv = 0;
|
||||
fail:
|
||||
close(filefd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* add file contents to a tarchive */
|
||||
int
|
||||
tar_append_file_contents(TAR *t, const char *savename, mode_t mode,
|
||||
uid_t uid, gid_t gid, void *buf, size_t len)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
st.st_mode = S_IFREG | mode;
|
||||
st.st_uid = uid;
|
||||
st.st_gid = gid;
|
||||
st.st_mtime = time(NULL);
|
||||
st.st_size = len;
|
||||
|
||||
th_set_from_stat(t, &st);
|
||||
th_set_path(t, savename);
|
||||
|
||||
/* write header */
|
||||
if (th_write(t) != 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "tar_append_file_contents(): could not write header, t->fd = %d\n", t->fd);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return tar_append_buffer(t, buf, len);
|
||||
}
|
||||
|
||||
int
|
||||
tar_append_buffer(TAR *t, void *buf, size_t len)
|
||||
{
|
||||
char block[T_BLOCKSIZE];
|
||||
int filefd;
|
||||
int i, j;
|
||||
size_t size = len;
|
||||
|
||||
for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE)
|
||||
{
|
||||
if (tar_block_write(t, buf) == -1)
|
||||
return -1;
|
||||
buf = (char *)buf + T_BLOCKSIZE;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
memcpy(block, buf, i);
|
||||
memset(&(block[i]), 0, T_BLOCKSIZE - i);
|
||||
if (tar_block_write(t, &block) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(filefd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ openbsd_basename(path)
|
||||
while (startp > path && *(startp - 1) != '/')
|
||||
startp--;
|
||||
|
||||
if (endp - startp + 1 > sizeof(bname)) {
|
||||
if (endp - startp + 1 > (int)sizeof(bname)) {
|
||||
errno = ENAMETOOLONG;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
+37
-52
@@ -11,7 +11,6 @@
|
||||
*/
|
||||
|
||||
#include <internal.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
@@ -27,6 +26,17 @@
|
||||
#define SELINUX_TAG_LEN 21
|
||||
|
||||
/* read a header block */
|
||||
/* FIXME: the return value of this function should match the return value
|
||||
of tar_block_read(), which is a macro which references a prototype
|
||||
that returns a ssize_t. So far, this is safe, since tar_block_read()
|
||||
only ever reads 512 (T_BLOCKSIZE) bytes at a time, so any difference
|
||||
in size of ssize_t and int is of negligible risk. BUT, if
|
||||
T_BLOCKSIZE ever changes, or ever becomes a variable parameter
|
||||
controllable by the user, all the code that calls it,
|
||||
including this function and all code that calls it, should be
|
||||
fixed for security reasons.
|
||||
Thanks to Chris Palmer for the critique.
|
||||
*/
|
||||
int
|
||||
th_read_internal(TAR *t)
|
||||
{
|
||||
@@ -93,8 +103,8 @@ th_read_internal(TAR *t)
|
||||
int
|
||||
th_read(TAR *t)
|
||||
{
|
||||
int i, j;
|
||||
size_t sz;
|
||||
int i;
|
||||
size_t sz, j, blocks;
|
||||
char *ptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -126,21 +136,26 @@ th_read(TAR *t)
|
||||
if (TH_ISLONGLINK(t))
|
||||
{
|
||||
sz = th_get_size(t);
|
||||
j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
|
||||
blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
|
||||
if (blocks > ((size_t)-1 / T_BLOCKSIZE))
|
||||
{
|
||||
errno = E2BIG;
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(" th_read(): GNU long linkname detected "
|
||||
"(%ld bytes, %d blocks)\n", sz, j);
|
||||
"(%ld bytes, %d blocks)\n", sz, blocks);
|
||||
#endif
|
||||
t->th_buf.gnu_longlink = (char *)malloc(j * T_BLOCKSIZE);
|
||||
t->th_buf.gnu_longlink = (char *)malloc(blocks * T_BLOCKSIZE);
|
||||
if (t->th_buf.gnu_longlink == NULL)
|
||||
return -1;
|
||||
|
||||
for (ptr = t->th_buf.gnu_longlink; j > 0;
|
||||
j--, ptr += T_BLOCKSIZE)
|
||||
for (j = 0, ptr = t->th_buf.gnu_longlink; j < blocks;
|
||||
j++, ptr += T_BLOCKSIZE)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf(" th_read(): reading long linkname "
|
||||
"(%d blocks left, ptr == %ld)\n", j, ptr);
|
||||
"(%d blocks left, ptr == %ld)\n", blocks-j, ptr);
|
||||
#endif
|
||||
i = tar_block_read(t, ptr);
|
||||
if (i != T_BLOCKSIZE)
|
||||
@@ -171,21 +186,26 @@ th_read(TAR *t)
|
||||
if (TH_ISLONGNAME(t))
|
||||
{
|
||||
sz = th_get_size(t);
|
||||
j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
|
||||
blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0);
|
||||
if (blocks > ((size_t)-1 / T_BLOCKSIZE))
|
||||
{
|
||||
errno = E2BIG;
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(" th_read(): GNU long filename detected "
|
||||
"(%ld bytes, %d blocks)\n", sz, j);
|
||||
"(%ld bytes, %d blocks)\n", sz, blocks);
|
||||
#endif
|
||||
t->th_buf.gnu_longname = (char *)malloc(j * T_BLOCKSIZE);
|
||||
t->th_buf.gnu_longname = (char *)malloc(blocks * T_BLOCKSIZE);
|
||||
if (t->th_buf.gnu_longname == NULL)
|
||||
return -1;
|
||||
|
||||
for (ptr = t->th_buf.gnu_longname; j > 0;
|
||||
j--, ptr += T_BLOCKSIZE)
|
||||
for (j = 0, ptr = t->th_buf.gnu_longname; j < blocks;
|
||||
j++, ptr += T_BLOCKSIZE)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf(" th_read(): reading long filename "
|
||||
"(%d blocks left, ptr == %ld)\n", j, ptr);
|
||||
"(%d blocks left, ptr == %ld)\n", blocks-j, ptr);
|
||||
#endif
|
||||
i = tar_block_read(t, ptr);
|
||||
if (i != T_BLOCKSIZE)
|
||||
@@ -263,41 +283,6 @@ th_read(TAR *t)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** work-around for old archive files with broken typeflag fields
|
||||
** NOTE: I fixed this in the TH_IS*() macros instead
|
||||
*/
|
||||
|
||||
/*
|
||||
** (directories are signified with a trailing '/')
|
||||
*/
|
||||
if (t->th_buf.typeflag == AREGTYPE
|
||||
&& t->th_buf.name[strlen(t->th_buf.name) - 1] == '/')
|
||||
t->th_buf.typeflag = DIRTYPE;
|
||||
|
||||
/*
|
||||
** fallback to using mode bits
|
||||
*/
|
||||
if (t->th_buf.typeflag == AREGTYPE)
|
||||
{
|
||||
mode = (mode_t)oct_to_int(t->th_buf.mode);
|
||||
|
||||
if (S_ISREG(mode))
|
||||
t->th_buf.typeflag = REGTYPE;
|
||||
else if (S_ISDIR(mode))
|
||||
t->th_buf.typeflag = DIRTYPE;
|
||||
else if (S_ISFIFO(mode))
|
||||
t->th_buf.typeflag = FIFOTYPE;
|
||||
else if (S_ISCHR(mode))
|
||||
t->th_buf.typeflag = CHRTYPE;
|
||||
else if (S_ISBLK(mode))
|
||||
t->th_buf.typeflag = BLKTYPE;
|
||||
else if (S_ISLNK(mode))
|
||||
t->th_buf.typeflag = SYMTYPE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -308,7 +293,7 @@ th_write(TAR *t)
|
||||
{
|
||||
int i, j;
|
||||
char type2;
|
||||
size_t sz, sz2;
|
||||
uint64_t sz, sz2;
|
||||
char *ptr;
|
||||
char buf[T_BLOCKSIZE];
|
||||
|
||||
@@ -457,7 +442,7 @@ th_write(TAR *t)
|
||||
}
|
||||
|
||||
memset(buf, 0, T_BLOCKSIZE);
|
||||
snprintf(buf, T_BLOCKSIZE, "%d "SELINUX_TAG"%s\n", sz, t->th_buf.selinux_context);
|
||||
snprintf(buf, T_BLOCKSIZE, "%d "SELINUX_TAG"%s\n", (int)sz, t->th_buf.selinux_context);
|
||||
i = tar_block_write(t, &buf);
|
||||
if (i != T_BLOCKSIZE)
|
||||
{
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
# include <libgen.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
#include "selinux/selinux.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(NEED_BASENAME) && !defined(HAVE_BASENAME)
|
||||
|
||||
|
||||
+32
-19
@@ -13,6 +13,7 @@
|
||||
#include <internal.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
@@ -26,22 +27,30 @@
|
||||
char *
|
||||
th_get_pathname(TAR *t)
|
||||
{
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (t->th_buf.gnu_longname) {
|
||||
printf("returning gnu longname\n");
|
||||
if (t->th_buf.gnu_longname)
|
||||
return t->th_buf.gnu_longname;
|
||||
}
|
||||
|
||||
if (t->th_buf.prefix[0] != '\0')
|
||||
/* allocate the th_pathname buffer if not already */
|
||||
if (t->th_pathname == NULL)
|
||||
{
|
||||
snprintf(filename, sizeof(filename), "%.155s/%.100s",
|
||||
t->th_buf.prefix, t->th_buf.name);
|
||||
return strdup(filename);
|
||||
t->th_pathname = malloc(MAXPATHLEN * sizeof(char));
|
||||
if (t->th_pathname == NULL)
|
||||
/* out of memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename), "%.100s", t->th_buf.name);
|
||||
return strdup(filename);
|
||||
if (t->th_buf.prefix[0] == '\0')
|
||||
{
|
||||
snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s",
|
||||
t->th_buf.prefix, t->th_buf.name);
|
||||
}
|
||||
|
||||
/* will be deallocated in tar_close() */
|
||||
return t->th_pathname;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,9 +60,11 @@ th_get_uid(TAR *t)
|
||||
int uid;
|
||||
struct passwd *pw;
|
||||
|
||||
pw = getpwnam(t->th_buf.uname);
|
||||
if (pw != NULL)
|
||||
return pw->pw_uid;
|
||||
if (!(t->options & TAR_USE_NUMERIC_ID)) {
|
||||
pw = getpwnam(t->th_buf.uname);
|
||||
if (pw != NULL)
|
||||
return pw->pw_uid;
|
||||
}
|
||||
|
||||
/* if the password entry doesn't exist */
|
||||
sscanf(t->th_buf.uid, "%o", &uid);
|
||||
@@ -67,9 +78,11 @@ th_get_gid(TAR *t)
|
||||
int gid;
|
||||
struct group *gr;
|
||||
|
||||
gr = getgrnam(t->th_buf.gname);
|
||||
if (gr != NULL)
|
||||
return gr->gr_gid;
|
||||
if (!(t->options & TAR_USE_NUMERIC_ID)) {
|
||||
gr = getgrnam(t->th_buf.gname);
|
||||
if (gr != NULL)
|
||||
return gr->gr_gid;
|
||||
}
|
||||
|
||||
/* if the group entry doesn't exist */
|
||||
sscanf(t->th_buf.gid, "%o", &gid);
|
||||
@@ -82,7 +95,7 @@ th_get_mode(TAR *t)
|
||||
{
|
||||
mode_t mode;
|
||||
|
||||
mode = (mode_t)oct_to_int(t->th_buf.mode);
|
||||
mode = (mode_t)oct_to_int(t->th_buf.mode, sizeof(t->th_buf.mode));
|
||||
if (! (mode & S_IFMT))
|
||||
{
|
||||
switch (t->th_buf.typeflag)
|
||||
@@ -103,7 +116,7 @@ th_get_mode(TAR *t)
|
||||
mode |= S_IFIFO;
|
||||
break;
|
||||
case AREGTYPE:
|
||||
if (t->th_buf.name[strlen(t->th_buf.name) - 1] == '/')
|
||||
if (t->th_buf.name[strnlen(t->th_buf.name, T_NAMELEN) - 1] == '/')
|
||||
{
|
||||
mode |= S_IFDIR;
|
||||
break;
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ openbsd_dirname(path)
|
||||
} while (endp > path && *endp == '/');
|
||||
}
|
||||
|
||||
if (endp - path + 1 > sizeof(bname)) {
|
||||
if (endp - path + 1 > (int)sizeof(bname)) {
|
||||
errno = ENAMETOOLONG;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
+54
-29
@@ -68,10 +68,11 @@ th_set_type(TAR *t, mode_t mode)
|
||||
|
||||
/* encode file path */
|
||||
void
|
||||
th_set_path(TAR *t, char *pathname)
|
||||
th_set_path(TAR *t, const char *pathname)
|
||||
{
|
||||
char suffix[2] = "";
|
||||
char *tmp;
|
||||
size_t pathname_len = strlen(pathname);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("in th_set_path(th, pathname=\"%s\")\n", pathname);
|
||||
@@ -81,32 +82,49 @@ th_set_path(TAR *t, char *pathname)
|
||||
free(t->th_buf.gnu_longname);
|
||||
t->th_buf.gnu_longname = NULL;
|
||||
|
||||
if (pathname[strlen(pathname) - 1] != '/' && TH_ISDIR(t))
|
||||
/* old archive compatibility (not needed for gnu): add trailing / to directories */
|
||||
if (pathname[pathname_len - 1] != '/' && TH_ISDIR(t))
|
||||
strcpy(suffix, "/");
|
||||
|
||||
if (strlen(pathname) > T_NAMELEN-1 && (t->options & TAR_GNU))
|
||||
if (pathname_len >= T_NAMELEN && (t->options & TAR_GNU))
|
||||
{
|
||||
/* GNU-style long name */
|
||||
/* GNU-style long name (no file name length limit) */
|
||||
t->th_buf.gnu_longname = strdup(pathname);
|
||||
strncpy(t->th_buf.name, t->th_buf.gnu_longname, T_NAMELEN);
|
||||
}
|
||||
else if (strlen(pathname) > T_NAMELEN)
|
||||
else if (pathname_len >= T_NAMELEN)
|
||||
{
|
||||
/* POSIX-style prefix field */
|
||||
tmp = strchr(&(pathname[strlen(pathname) - T_NAMELEN - 1]), '/');
|
||||
/* POSIX-style prefix field:
|
||||
* The maximum length of a file name is limited to 256 characters,
|
||||
* provided that the file name can be split at a directory separator
|
||||
* in two parts. The first part being at most 155 bytes long and
|
||||
* the second part being at most 100 bytes long. So, in most cases
|
||||
* the maximum file name length will be shorter than 256 characters.
|
||||
*/
|
||||
char tail_path[T_NAMELEN + 1];
|
||||
tmp = strchr(&(pathname[pathname_len - T_NAMELEN]), '/');
|
||||
if (tmp == NULL)
|
||||
{
|
||||
printf("!!! '/' not found in \"%s\"\n", pathname);
|
||||
return;
|
||||
}
|
||||
snprintf(t->th_buf.name, 100, "%s%s", &(tmp[1]), suffix);
|
||||
snprintf(t->th_buf.prefix,
|
||||
((tmp - pathname + 1) <
|
||||
155 ? (tmp - pathname + 1) : 155), "%s", pathname);
|
||||
snprintf(tail_path, T_NAMELEN + 1, "%s%s", &tmp[1], suffix);
|
||||
strncpy(t->th_buf.name, tail_path, T_NAMELEN);
|
||||
|
||||
/*
|
||||
* first part, max = 155 == sizeof(t->th_buf.prefix) , include NULL if it fits
|
||||
* trailing '/' is added during decode: decode.c/th_get_pathname()
|
||||
*/
|
||||
if (tmp - pathname >= 155) {
|
||||
strncpy(t->th_buf.prefix, pathname, 155);
|
||||
} else {
|
||||
snprintf(t->th_buf.prefix, (tmp - pathname + 1), "%s", pathname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* any short name for all formats, or classic tar format (99 chars max) */
|
||||
snprintf(t->th_buf.name, T_NAMELEN, "%s%s", pathname, suffix);
|
||||
}
|
||||
else
|
||||
/* classic tar format */
|
||||
snprintf(t->th_buf.name, 100, "%s%s", pathname, suffix);
|
||||
|
||||
#ifdef DEBUG
|
||||
puts("returning from th_set_path()...");
|
||||
@@ -116,23 +134,28 @@ th_set_path(TAR *t, char *pathname)
|
||||
|
||||
/* encode link path */
|
||||
void
|
||||
th_set_link(TAR *t, char *linkname)
|
||||
th_set_link(TAR *t, const char *linkname)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("==> th_set_link(th, linkname=\"%s\")\n", linkname);
|
||||
#endif
|
||||
|
||||
if (strlen(linkname) > T_NAMELEN-1 && (t->options & TAR_GNU))
|
||||
if (strlen(linkname) >= T_NAMELEN && (t->options & TAR_GNU))
|
||||
{
|
||||
/* GNU longlink format */
|
||||
/* --format=gnu: GNU-style long name (no file name length limit) */
|
||||
t->th_buf.gnu_longlink = strdup(linkname);
|
||||
strcpy(t->th_buf.linkname, "././@LongLink");
|
||||
}
|
||||
else
|
||||
else if (strlen(linkname) >= T_NAMELEN)
|
||||
{
|
||||
/* classic tar format */
|
||||
strlcpy(t->th_buf.linkname, linkname,
|
||||
sizeof(t->th_buf.linkname));
|
||||
/* --format=ustar: 100 chars max limit for symbolic links */
|
||||
strncpy(t->th_buf.linkname, linkname, T_NAMELEN);
|
||||
if (t->th_buf.gnu_longlink != NULL)
|
||||
free(t->th_buf.gnu_longlink);
|
||||
t->th_buf.gnu_longlink = NULL;
|
||||
} else {
|
||||
/* all short links or v7 tar format: The maximum length of a symbolic link name is limited to 99 characters */
|
||||
snprintf(t->th_buf.linkname, T_NAMELEN, "%s", linkname);
|
||||
if (t->th_buf.gnu_longlink != NULL)
|
||||
free(t->th_buf.gnu_longlink);
|
||||
t->th_buf.gnu_longlink = NULL;
|
||||
@@ -159,9 +182,11 @@ th_set_user(TAR *t, uid_t uid)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if (pw != NULL)
|
||||
strlcpy(t->th_buf.uname, pw->pw_name, sizeof(t->th_buf.uname));
|
||||
if (!(t->options & TAR_USE_NUMERIC_ID)) {
|
||||
pw = getpwuid(uid);
|
||||
if (pw != NULL)
|
||||
strlcpy(t->th_buf.uname, pw->pw_name, sizeof(t->th_buf.uname));
|
||||
}
|
||||
|
||||
int_to_oct(uid, t->th_buf.uid, 8);
|
||||
}
|
||||
@@ -173,9 +198,11 @@ th_set_group(TAR *t, gid_t gid)
|
||||
{
|
||||
struct group *gr;
|
||||
|
||||
gr = getgrgid(gid);
|
||||
if (gr != NULL)
|
||||
strlcpy(t->th_buf.gname, gr->gr_name, sizeof(t->th_buf.gname));
|
||||
if (!(t->options & TAR_USE_NUMERIC_ID)) {
|
||||
gr = getgrgid(gid);
|
||||
if (gr != NULL)
|
||||
strlcpy(t->th_buf.gname, gr->gr_name, sizeof(t->th_buf.gname));
|
||||
}
|
||||
|
||||
int_to_oct(gid, t->th_buf.gid, 8);
|
||||
}
|
||||
@@ -209,5 +236,3 @@ th_set_from_stat(TAR *t, struct stat *s)
|
||||
else
|
||||
th_set_size(t, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+171
-140
@@ -13,14 +13,13 @@
|
||||
#include <internal.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <utime.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
@@ -29,26 +28,30 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define DEBUG
|
||||
#ifdef HAVE_SELINUX
|
||||
# include "selinux/selinux.h"
|
||||
#endif
|
||||
|
||||
static int
|
||||
tar_set_file_perms(TAR *t, char *realname)
|
||||
tar_set_file_perms(TAR *t, const char *realname)
|
||||
{
|
||||
mode_t mode;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
struct utimbuf ut;
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
mode = th_get_mode(t);
|
||||
uid = th_get_uid(t);
|
||||
gid = th_get_gid(t);
|
||||
ut.modtime = ut.actime = th_get_mtime(t);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" ==> setting perms: %s (mode %04o, uid %d, gid %d)\n",
|
||||
filename, mode, uid, gid);
|
||||
printf("tar_set_file_perms(): setting perms: %s (mode %04o, uid %d, gid %d)\n",
|
||||
filename, mode, uid, gid);
|
||||
#endif
|
||||
|
||||
/* change owner/group */
|
||||
@@ -95,12 +98,15 @@ tar_set_file_perms(TAR *t, char *realname)
|
||||
|
||||
/* switchboard */
|
||||
int
|
||||
tar_extract_file(TAR *t, char *realname, char *prefix, const int *progress_fd)
|
||||
tar_extract_file(TAR *t, const char *realname, const char *prefix, const int *progress_fd)
|
||||
{
|
||||
int i;
|
||||
#ifdef LIBTAR_FILE_HASH
|
||||
char *lnp;
|
||||
char *pn;
|
||||
int pathname_len;
|
||||
int realname_len;
|
||||
#endif
|
||||
|
||||
if (t->options & TAR_NOOVERWRITE)
|
||||
{
|
||||
@@ -115,44 +121,31 @@ tar_extract_file(TAR *t, char *realname, char *prefix, const int *progress_fd)
|
||||
|
||||
if (TH_ISDIR(t))
|
||||
{
|
||||
printf("dir\n");
|
||||
i = tar_extract_dir(t, realname);
|
||||
if (i == 1)
|
||||
i = 0;
|
||||
}
|
||||
else if (TH_ISLNK(t)) {
|
||||
printf("link\n");
|
||||
else if (TH_ISLNK(t))
|
||||
i = tar_extract_hardlink(t, realname, prefix);
|
||||
}
|
||||
else if (TH_ISSYM(t)) {
|
||||
printf("sym\n");
|
||||
else if (TH_ISSYM(t))
|
||||
i = tar_extract_symlink(t, realname);
|
||||
}
|
||||
else if (TH_ISCHR(t)) {
|
||||
printf("chr\n");
|
||||
else if (TH_ISCHR(t))
|
||||
i = tar_extract_chardev(t, realname);
|
||||
}
|
||||
else if (TH_ISBLK(t)) {
|
||||
printf("blk\n");
|
||||
else if (TH_ISBLK(t))
|
||||
i = tar_extract_blockdev(t, realname);
|
||||
}
|
||||
else if (TH_ISFIFO(t)) {
|
||||
printf("fifo\n");
|
||||
else if (TH_ISFIFO(t))
|
||||
i = tar_extract_fifo(t, realname);
|
||||
}
|
||||
else /* if (TH_ISREG(t)) */ {
|
||||
printf("reg\n");
|
||||
else /* if (TH_ISREG(t)) */
|
||||
i = tar_extract_regfile(t, realname, progress_fd);
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
printf("FAILED RESTORE OF FILE i: %s\n", realname);
|
||||
fprintf(stderr, "tar_extract_file(): failed to extract %s !!!\n", realname);
|
||||
return i;
|
||||
}
|
||||
|
||||
i = tar_set_file_perms(t, realname);
|
||||
if (i != 0) {
|
||||
printf("FAILED SETTING PERMS: %d\n", i);
|
||||
fprintf(stderr, "tar_extract_file(): failed to set permissions on %s !!!\n", realname);
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -160,51 +153,48 @@ tar_extract_file(TAR *t, char *realname, char *prefix, const int *progress_fd)
|
||||
if((t->options & TAR_STORE_SELINUX) && t->th_buf.selinux_context != NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf(" Restoring SELinux context %s to file %s\n", t->th_buf.selinux_context, realname);
|
||||
printf("tar_extract_file(): restoring SELinux context %s to file %s\n", t->th_buf.selinux_context, realname);
|
||||
#endif
|
||||
if (lsetfilecon(realname, t->th_buf.selinux_context) < 0) {
|
||||
fprintf(stderr, "Failed to restore SELinux context %s!\n", strerror(errno));
|
||||
}
|
||||
if (lsetfilecon(realname, t->th_buf.selinux_context) < 0)
|
||||
fprintf(stderr, "tar_extract_file(): failed to restore SELinux context %s to file %s !!!\n", t->th_buf.selinux_context, realname);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
pathname_len = strlen(th_get_pathname(t)) + 1;
|
||||
#ifdef LIBTAR_FILE_HASH
|
||||
pn = th_get_pathname(t);
|
||||
pathname_len = strlen(pn) + 1;
|
||||
realname_len = strlen(realname) + 1;
|
||||
lnp = (char *)calloc(1, pathname_len + realname_len);
|
||||
if (lnp == NULL)
|
||||
return -1;
|
||||
strcpy(&lnp[0], th_get_pathname(t));
|
||||
strcpy(&lnp[0], pn);
|
||||
strcpy(&lnp[pathname_len], realname);
|
||||
#ifdef DEBUG
|
||||
printf("tar_extract_file(): calling libtar_hash_add(): key=\"%s\", "
|
||||
"value=\"%s\"\n", th_get_pathname(t), realname);
|
||||
"value=\"%s\"\n", pn, realname);
|
||||
#endif
|
||||
if (libtar_hash_add(t->h, lnp) != 0)
|
||||
return -1;
|
||||
free(lnp);
|
||||
*/
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* extract regular file */
|
||||
int
|
||||
tar_extract_regfile(TAR *t, char *realname, const int *progress_fd)
|
||||
tar_extract_regfile(TAR *t, const char *realname, const int *progress_fd)
|
||||
{
|
||||
//mode_t mode;
|
||||
size_t size, i;
|
||||
//uid_t uid;
|
||||
//gid_t gid;
|
||||
int64_t size, i;
|
||||
ssize_t k;
|
||||
int fdout;
|
||||
int k;
|
||||
char buf[T_BLOCKSIZE];
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
|
||||
fflush(NULL);
|
||||
#ifdef DEBUG
|
||||
printf("==> tar_extract_regfile(t=0x%lx, realname=\"%s\")\n", t,
|
||||
realname);
|
||||
printf(" ==> tar_extract_regfile(realname=\"%s\")\n", realname);
|
||||
#endif
|
||||
|
||||
if (!TH_ISREG(t))
|
||||
@@ -213,21 +203,16 @@ tar_extract_regfile(TAR *t, char *realname, const int *progress_fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
//mode = th_get_mode(t);
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
size = th_get_size(t);
|
||||
//uid = th_get_uid(t);
|
||||
//gid = th_get_gid(t);
|
||||
|
||||
if (mkdirhier(dirname(filename)) == -1)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
//printf(" ==> extracting: %s (mode %04o, uid %d, gid %d, %d bytes)\n",
|
||||
// filename, mode, uid, gid, size);
|
||||
printf(" ==> extracting: %s (file size %d bytes)\n",
|
||||
filename, size);
|
||||
#endif
|
||||
printf(" ==> extracting: %s (file size %lld bytes)\n",
|
||||
filename, size);
|
||||
|
||||
fdout = open(filename, O_WRONLY | O_CREAT | O_TRUNC
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY
|
||||
@@ -241,41 +226,25 @@ tar_extract_regfile(TAR *t, char *realname, const int *progress_fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* change the owner. (will only work if run as root) */
|
||||
if (fchown(fdout, uid, gid) == -1 && errno != EPERM)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("fchown()");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make sure the mode isn't inheritted from a file we're overwriting */
|
||||
if (fchmod(fdout, mode & 07777) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("fchmod()");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* extract the file */
|
||||
for (i = size; i > 0; i -= tar_min(i, T_BLOCKSIZE))
|
||||
for (i = size; i > 0; i -= T_BLOCKSIZE)
|
||||
{
|
||||
k = tar_block_read(t, buf);
|
||||
if (k != T_BLOCKSIZE)
|
||||
{
|
||||
if (k != -1)
|
||||
errno = EINVAL;
|
||||
close(fdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* write block to output file */
|
||||
if (write(fdout, buf,
|
||||
((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1)
|
||||
{
|
||||
close(fdout);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* close output file */
|
||||
@@ -286,7 +255,8 @@ tar_extract_regfile(TAR *t, char *realname, const int *progress_fd)
|
||||
printf("### done extracting %s\n", filename);
|
||||
#endif
|
||||
|
||||
if (*progress_fd != 0) {
|
||||
if (*progress_fd != 0)
|
||||
{
|
||||
unsigned long long file_size = (unsigned long long)(size);
|
||||
write(*progress_fd, &file_size, sizeof(file_size));
|
||||
}
|
||||
@@ -299,8 +269,8 @@ tar_extract_regfile(TAR *t, char *realname, const int *progress_fd)
|
||||
int
|
||||
tar_skip_regfile(TAR *t)
|
||||
{
|
||||
int k;
|
||||
size_t size, i;
|
||||
int64_t size, i;
|
||||
ssize_t k;
|
||||
char buf[T_BLOCKSIZE];
|
||||
|
||||
if (!TH_ISREG(t))
|
||||
@@ -310,7 +280,7 @@ tar_skip_regfile(TAR *t)
|
||||
}
|
||||
|
||||
size = th_get_size(t);
|
||||
for (i = size; i > 0; i -= tar_min(i, T_BLOCKSIZE))
|
||||
for (i = size; i > 0; i -= T_BLOCKSIZE)
|
||||
{
|
||||
k = tar_block_read(t, buf);
|
||||
if (k != T_BLOCKSIZE)
|
||||
@@ -327,10 +297,12 @@ tar_skip_regfile(TAR *t)
|
||||
|
||||
/* hardlink */
|
||||
int
|
||||
tar_extract_hardlink(TAR * t, char *realname, char *prefix)
|
||||
tar_extract_hardlink(TAR * t, const char *realname, const char *prefix)
|
||||
{
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
char *linktgt = NULL;
|
||||
char *newtgt = NULL;
|
||||
char *lnp;
|
||||
libtar_hashptr_t hp;
|
||||
|
||||
@@ -340,9 +312,12 @@ tar_extract_hardlink(TAR * t, char *realname, char *prefix)
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
if (mkdirhier(dirname(filename)) == -1)
|
||||
return -1;
|
||||
if (unlink(filename) == -1 && errno != ENOENT)
|
||||
return -1;
|
||||
libtar_hashptr_reset(&hp);
|
||||
if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t),
|
||||
(libtar_matchfunc_t)libtar_str_match) != 0)
|
||||
@@ -352,17 +327,15 @@ tar_extract_hardlink(TAR * t, char *realname, char *prefix)
|
||||
}
|
||||
else
|
||||
linktgt = th_get_linkname(t);
|
||||
char *newtgt = strdup(linktgt);
|
||||
|
||||
newtgt = strdup(linktgt);
|
||||
sprintf(linktgt, "%s/%s", prefix, newtgt);
|
||||
#ifdef DEBUG
|
||||
|
||||
printf(" ==> extracting: %s (link to %s)\n", filename, linktgt);
|
||||
#endif
|
||||
|
||||
if (link(linktgt, filename) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("link()");
|
||||
#endif
|
||||
printf("Failed restore of hardlink '%s' but returning as if nothing bad happened anyway\n", filename);
|
||||
fprintf(stderr, "tar_extract_hardlink(): failed restore of hardlink '%s' but returning as if nothing bad happened\n", filename);
|
||||
return 0; // Used to be -1
|
||||
}
|
||||
|
||||
@@ -372,33 +345,28 @@ tar_extract_hardlink(TAR * t, char *realname, char *prefix)
|
||||
|
||||
/* symlink */
|
||||
int
|
||||
tar_extract_symlink(TAR *t, char *realname)
|
||||
tar_extract_symlink(TAR *t, const char *realname)
|
||||
{
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
|
||||
if (!TH_ISSYM(t))
|
||||
{
|
||||
printf("not a sym\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
printf("file: %s\n", filename);
|
||||
if (mkdirhier(dirname(filename)) == -1) {
|
||||
printf("mkdirhier\n");
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
if (mkdirhier(dirname(filename)) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlink(filename) == -1 && errno != ENOENT) {
|
||||
printf("unlink\n");
|
||||
if (unlink(filename) == -1 && errno != ENOENT)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" ==> extracting: %s (symlink to %s)\n",
|
||||
filename, th_get_linkname(t));
|
||||
#endif
|
||||
|
||||
if (symlink(th_get_linkname(t), filename) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -413,11 +381,12 @@ tar_extract_symlink(TAR *t, char *realname)
|
||||
|
||||
/* character device */
|
||||
int
|
||||
tar_extract_chardev(TAR *t, char *realname)
|
||||
tar_extract_chardev(TAR *t, const char *realname)
|
||||
{
|
||||
mode_t mode;
|
||||
unsigned long devmaj, devmin;
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
|
||||
if (!TH_ISCHR(t))
|
||||
{
|
||||
@@ -425,7 +394,8 @@ tar_extract_chardev(TAR *t, char *realname)
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
mode = th_get_mode(t);
|
||||
devmaj = th_get_devmajor(t);
|
||||
devmin = th_get_devminor(t);
|
||||
@@ -433,17 +403,14 @@ tar_extract_chardev(TAR *t, char *realname)
|
||||
if (mkdirhier(dirname(filename)) == -1)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" ==> extracting: %s (character device %ld,%ld)\n",
|
||||
filename, devmaj, devmin);
|
||||
#endif
|
||||
|
||||
if (mknod(filename, mode | S_IFCHR,
|
||||
compat_makedev(devmaj, devmin)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("mknod() failed, returning good anyway");
|
||||
#endif
|
||||
return 0;
|
||||
fprintf(stderr, "tar_extract_chardev(): failed restore of character device '%s' but returning as if nothing bad happened\n", filename);
|
||||
return 0; // Used to be -1
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -452,11 +419,12 @@ tar_extract_chardev(TAR *t, char *realname)
|
||||
|
||||
/* block device */
|
||||
int
|
||||
tar_extract_blockdev(TAR *t, char *realname)
|
||||
tar_extract_blockdev(TAR *t, const char *realname)
|
||||
{
|
||||
mode_t mode;
|
||||
unsigned long devmaj, devmin;
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
|
||||
if (!TH_ISBLK(t))
|
||||
{
|
||||
@@ -464,7 +432,8 @@ tar_extract_blockdev(TAR *t, char *realname)
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
mode = th_get_mode(t);
|
||||
devmaj = th_get_devmajor(t);
|
||||
devmin = th_get_devminor(t);
|
||||
@@ -472,17 +441,14 @@ tar_extract_blockdev(TAR *t, char *realname)
|
||||
if (mkdirhier(dirname(filename)) == -1)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" ==> extracting: %s (block device %ld,%ld)\n",
|
||||
filename, devmaj, devmin);
|
||||
#endif
|
||||
|
||||
if (mknod(filename, mode | S_IFBLK,
|
||||
compat_makedev(devmaj, devmin)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("mknod() failed but returning anyway");
|
||||
#endif
|
||||
return 0;
|
||||
fprintf(stderr, "tar_extract_blockdev(): failed restore of block device '%s' but returning as if nothing bad happened\n", filename);
|
||||
return 0; // Used to be -1
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -491,35 +457,45 @@ tar_extract_blockdev(TAR *t, char *realname)
|
||||
|
||||
/* directory */
|
||||
int
|
||||
tar_extract_dir(TAR *t, char *realname)
|
||||
tar_extract_dir(TAR *t, const char *realname)
|
||||
{
|
||||
mode_t mode;
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
|
||||
if (!TH_ISDIR(t))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
mode = th_get_mode(t);
|
||||
|
||||
if (mkdirhier(dirname(filename)) == -1) {
|
||||
printf("tar_extract_dir mkdirhier failed\n");
|
||||
if (mkdirhier(dirname(filename)) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" ==> extracting: %s (mode %04o, directory)\n", filename,
|
||||
mode);
|
||||
#endif
|
||||
|
||||
if (mkdir(filename, mode) == -1)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
{
|
||||
if (chmod(filename, mode) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf(" *** using existing directory");
|
||||
perror("chmod()");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
puts(" *** using existing directory");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -536,10 +512,11 @@ tar_extract_dir(TAR *t, char *realname)
|
||||
|
||||
/* FIFO */
|
||||
int
|
||||
tar_extract_fifo(TAR *t, char *realname)
|
||||
tar_extract_fifo(TAR *t, const char *realname)
|
||||
{
|
||||
mode_t mode;
|
||||
char *filename;
|
||||
const char *filename;
|
||||
char *pn;
|
||||
|
||||
if (!TH_ISFIFO(t))
|
||||
{
|
||||
@@ -547,15 +524,16 @@ tar_extract_fifo(TAR *t, char *realname)
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = (realname ? realname : th_get_pathname(t));
|
||||
pn = th_get_pathname(t);
|
||||
filename = (realname ? realname : pn);
|
||||
mode = th_get_mode(t);
|
||||
|
||||
if (mkdirhier(dirname(filename)) == -1)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
printf(" ==> extracting: %s (fifo)\n", filename);
|
||||
#endif
|
||||
|
||||
if (mkfifo(filename, mode) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -567,4 +545,57 @@ tar_extract_fifo(TAR *t, char *realname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* extract file contents from a tarchive */
|
||||
int
|
||||
tar_extract_file_contents(TAR *t, void *buf, size_t *lenp)
|
||||
{
|
||||
char block[T_BLOCKSIZE];
|
||||
int64_t size, i;
|
||||
ssize_t k;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" ==> tar_extract_file_contents\n");
|
||||
#endif
|
||||
|
||||
if (!TH_ISREG(t))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = th_get_size(t);
|
||||
if ((uint64_t)size > *lenp)
|
||||
{
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* extract the file */
|
||||
for (i = size; i >= T_BLOCKSIZE; i -= T_BLOCKSIZE)
|
||||
{
|
||||
k = tar_block_read(t, buf);
|
||||
if (k != T_BLOCKSIZE)
|
||||
{
|
||||
if (k != -1)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
buf = (char *)buf + T_BLOCKSIZE;
|
||||
}
|
||||
if (i > 0) {
|
||||
k = tar_block_read(t, block);
|
||||
if (k != T_BLOCKSIZE)
|
||||
{
|
||||
if (k != -1)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf, block, i);
|
||||
}
|
||||
*lenp = (size_t)size;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("### done extracting contents\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
+6
-3
@@ -31,7 +31,7 @@ static tartype_t default_type = { open, close, read, write };
|
||||
|
||||
|
||||
static int
|
||||
tar_init(TAR **t, char *pathname, tartype_t *type,
|
||||
tar_init(TAR **t, const char *pathname, tartype_t *type,
|
||||
int oflags, int mode, int options)
|
||||
{
|
||||
if ((oflags & O_ACCMODE) == O_RDWR)
|
||||
@@ -66,7 +66,7 @@ tar_init(TAR **t, char *pathname, tartype_t *type,
|
||||
|
||||
/* open a new tarfile handle */
|
||||
int
|
||||
tar_open(TAR **t, char *pathname, tartype_t *type,
|
||||
tar_open(TAR **t, const char *pathname, tartype_t *type,
|
||||
int oflags, int mode, int options)
|
||||
{
|
||||
if (tar_init(t, pathname, type, oflags, mode, options) == -1)
|
||||
@@ -82,6 +82,7 @@ tar_open(TAR **t, char *pathname, tartype_t *type,
|
||||
(*t)->fd = (*((*t)->type->openfunc))(pathname, oflags, mode);
|
||||
if ((*t)->fd == -1)
|
||||
{
|
||||
libtar_hash_free((*t)->h, NULL);
|
||||
free(*t);
|
||||
return -1;
|
||||
}
|
||||
@@ -91,7 +92,7 @@ tar_open(TAR **t, char *pathname, tartype_t *type,
|
||||
|
||||
|
||||
int
|
||||
tar_fdopen(TAR **t, int fd, char *pathname, tartype_t *type,
|
||||
tar_fdopen(TAR **t, int fd, const char *pathname, tartype_t *type,
|
||||
int oflags, int mode, int options)
|
||||
{
|
||||
if (tar_init(t, pathname, type, oflags, mode, options) == -1)
|
||||
@@ -121,6 +122,8 @@ tar_close(TAR *t)
|
||||
libtar_hash_free(t->h, ((t->oflags & O_ACCMODE) == O_RDONLY
|
||||
? free
|
||||
: (libtar_freefunc_t)tar_dev_free));
|
||||
if (t->th_pathname != NULL)
|
||||
free(t->th_pathname);
|
||||
free(t);
|
||||
|
||||
return i;
|
||||
|
||||
+58
-36
@@ -26,6 +26,7 @@ extern "C"
|
||||
|
||||
|
||||
/* useful constants */
|
||||
/* see FIXME note in block.c regarding T_BLOCKSIZE */
|
||||
#define T_BLOCKSIZE 512
|
||||
#define T_NAMELEN 100
|
||||
#define T_PREFIXLEN 155
|
||||
@@ -85,12 +86,15 @@ tartype_t;
|
||||
typedef struct
|
||||
{
|
||||
tartype_t *type;
|
||||
char *pathname;
|
||||
const char *pathname;
|
||||
long fd;
|
||||
int oflags;
|
||||
int options;
|
||||
struct tar_header th_buf;
|
||||
libtar_hash_t *h;
|
||||
|
||||
/* introduced in libtar 1.2.21 */
|
||||
char *th_pathname;
|
||||
}
|
||||
TAR;
|
||||
|
||||
@@ -103,6 +107,7 @@ TAR;
|
||||
#define TAR_CHECK_VERSION 32 /* check version in file header */
|
||||
#define TAR_IGNORE_CRC 64 /* ignore CRC in file header */
|
||||
#define TAR_STORE_SELINUX 128 /* store selinux context */
|
||||
#define TAR_USE_NUMERIC_ID 256 /* favor numeric owner over names */
|
||||
|
||||
/* this is obsolete - it's here for backwards-compatibility only */
|
||||
#define TAR_IGNORE_MAGIC 0
|
||||
@@ -111,11 +116,11 @@ extern const char libtar_version[];
|
||||
|
||||
|
||||
/* open a new tarfile handle */
|
||||
int tar_open(TAR **t, char *pathname, tartype_t *type,
|
||||
int tar_open(TAR **t, const char *pathname, tartype_t *type,
|
||||
int oflags, int mode, int options);
|
||||
|
||||
/* make a tarfile handle out of a previously-opened descriptor */
|
||||
int tar_fdopen(TAR **t, int fd, char *pathname, tartype_t *type,
|
||||
int tar_fdopen(TAR **t, int fd, const char *pathname, tartype_t *type,
|
||||
int oflags, int mode, int options);
|
||||
|
||||
/* returns the descriptor associated with t */
|
||||
@@ -139,14 +144,27 @@ void tar_dev_free(struct tar_dev *tdp);
|
||||
* realname = path of file to append
|
||||
* savename = name to save the file under in the archive
|
||||
*/
|
||||
int tar_append_file(TAR *t, char *realname, char *savename);
|
||||
int tar_append_file(TAR *t, const char *realname, const char *savename);
|
||||
|
||||
/* write EOF indicator */
|
||||
int tar_append_eof(TAR *t);
|
||||
|
||||
/* add file contents to a tarchive */
|
||||
int tar_append_regfile(TAR *t, char *realname);
|
||||
int tar_append_regfile(TAR *t, const char *realname);
|
||||
|
||||
/* Appends in-memory file contents to a tarchive.
|
||||
* Arguments:
|
||||
* t = TAR handle to append to
|
||||
* savename = name to save the file under in the archive
|
||||
* mode = mode
|
||||
* uid, gid = owner
|
||||
* buf, len = in-memory buffer
|
||||
*/
|
||||
int tar_append_file_contents(TAR *t, const char *savename, mode_t mode,
|
||||
uid_t uid, gid_t gid, void *buf, size_t len);
|
||||
|
||||
/* add buffer to a tarchive */
|
||||
int tar_append_buffer(TAR *t, void *buf, size_t len);
|
||||
|
||||
/***** block.c *************************************************************/
|
||||
|
||||
@@ -167,31 +185,32 @@ int th_write(TAR *t);
|
||||
#define TH_ISREG(t) ((t)->th_buf.typeflag == REGTYPE \
|
||||
|| (t)->th_buf.typeflag == AREGTYPE \
|
||||
|| (t)->th_buf.typeflag == CONTTYPE \
|
||||
|| (S_ISREG((mode_t)oct_to_int((t)->th_buf.mode)) \
|
||||
|| (S_ISREG((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))) \
|
||||
&& (t)->th_buf.typeflag != LNKTYPE))
|
||||
#define TH_ISLNK(t) ((t)->th_buf.typeflag == LNKTYPE)
|
||||
#define TH_ISSYM(t) ((t)->th_buf.typeflag == SYMTYPE \
|
||||
|| S_ISLNK((mode_t)oct_to_int((t)->th_buf.mode)))
|
||||
|| S_ISLNK((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
|
||||
#define TH_ISCHR(t) ((t)->th_buf.typeflag == CHRTYPE \
|
||||
|| S_ISCHR((mode_t)oct_to_int((t)->th_buf.mode)))
|
||||
|| S_ISCHR((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
|
||||
#define TH_ISBLK(t) ((t)->th_buf.typeflag == BLKTYPE \
|
||||
|| S_ISBLK((mode_t)oct_to_int((t)->th_buf.mode)))
|
||||
|| S_ISBLK((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
|
||||
#define TH_ISDIR(t) ((t)->th_buf.typeflag == DIRTYPE \
|
||||
|| S_ISDIR((mode_t)oct_to_int((t)->th_buf.mode)) \
|
||||
|| S_ISDIR((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))) \
|
||||
|| ((t)->th_buf.typeflag == AREGTYPE \
|
||||
&& ((t)->th_buf.name[strlen((t)->th_buf.name) - 1] == '/')))
|
||||
&& strnlen((t)->th_buf.name, T_NAMELEN) \
|
||||
&& ((t)->th_buf.name[strnlen((t)->th_buf.name, T_NAMELEN) - 1] == '/')))
|
||||
#define TH_ISFIFO(t) ((t)->th_buf.typeflag == FIFOTYPE \
|
||||
|| S_ISFIFO((mode_t)oct_to_int((t)->th_buf.mode)))
|
||||
|| S_ISFIFO((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
|
||||
#define TH_ISLONGNAME(t) ((t)->th_buf.typeflag == GNU_LONGNAME_TYPE)
|
||||
#define TH_ISLONGLINK(t) ((t)->th_buf.typeflag == GNU_LONGLINK_TYPE)
|
||||
#define TH_ISEXTHEADER(t) ((t)->th_buf.typeflag == TH_EXT_TYPE)
|
||||
|
||||
/* decode tar header info */
|
||||
#define th_get_crc(t) oct_to_int((t)->th_buf.chksum)
|
||||
#define th_get_size(t) oct_to_int((t)->th_buf.size)
|
||||
#define th_get_mtime(t) oct_to_int((t)->th_buf.mtime)
|
||||
#define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor)
|
||||
#define th_get_devminor(t) oct_to_int((t)->th_buf.devminor)
|
||||
#define th_get_crc(t) oct_to_int((t)->th_buf.chksum, sizeof((t)->th_buf.chksum))
|
||||
#define th_get_size(t) oct_to_int_ex((t)->th_buf.size, sizeof((t)->th_buf.size))
|
||||
#define th_get_mtime(t) oct_to_int_ex((t)->th_buf.mtime, sizeof((t)->th_buf.mtime))
|
||||
#define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor, sizeof((t)->th_buf.devmajor))
|
||||
#define th_get_devminor(t) oct_to_int((t)->th_buf.devminor, sizeof((t)->th_buf.devminor))
|
||||
#define th_get_linkname(t) ((t)->th_buf.gnu_longlink \
|
||||
? (t)->th_buf.gnu_longlink \
|
||||
: (t)->th_buf.linkname)
|
||||
@@ -205,16 +224,16 @@ gid_t th_get_gid(TAR *t);
|
||||
|
||||
/* encode file info in th_header */
|
||||
void th_set_type(TAR *t, mode_t mode);
|
||||
void th_set_path(TAR *t, char *pathname);
|
||||
void th_set_link(TAR *t, char *linkname);
|
||||
void th_set_path(TAR *t, const char *pathname);
|
||||
void th_set_link(TAR *t, const char *linkname);
|
||||
void th_set_device(TAR *t, dev_t device);
|
||||
void th_set_user(TAR *t, uid_t uid);
|
||||
void th_set_group(TAR *t, gid_t gid);
|
||||
void th_set_mode(TAR *t, mode_t fmode);
|
||||
#define th_set_mtime(t, fmtime) \
|
||||
int_to_oct_nonull((fmtime), (t)->th_buf.mtime, 12)
|
||||
int_to_oct_ex((fmtime), (t)->th_buf.mtime, sizeof((t)->th_buf.mtime))
|
||||
#define th_set_size(t, fsize) \
|
||||
int_to_oct_nonull((fsize), (t)->th_buf.size, 12)
|
||||
int_to_oct_ex((fsize), (t)->th_buf.size, sizeof((t)->th_buf.size))
|
||||
|
||||
/* encode everything at once (except the pathname and linkname) */
|
||||
void th_set_from_stat(TAR *t, struct stat *s);
|
||||
@@ -226,20 +245,22 @@ void th_finish(TAR *t);
|
||||
/***** extract.c ***********************************************************/
|
||||
|
||||
/* sequentially extract next file from t */
|
||||
int tar_extract_file(TAR *t, char *realname, char *prefix, const int *progress_fd);
|
||||
int tar_extract_file(TAR *t, const char *realname, const char *prefix, const int *progress_fd);
|
||||
|
||||
/* extract different file types */
|
||||
int tar_extract_dir(TAR *t, char *realname);
|
||||
int tar_extract_hardlink(TAR *t, char *realname, char *prefix);
|
||||
int tar_extract_symlink(TAR *t, char *realname);
|
||||
int tar_extract_chardev(TAR *t, char *realname);
|
||||
int tar_extract_blockdev(TAR *t, char *realname);
|
||||
int tar_extract_fifo(TAR *t, char *realname);
|
||||
int tar_extract_dir(TAR *t, const char *realname);
|
||||
int tar_extract_hardlink(TAR *t, const char *realname, const char *prefix);
|
||||
int tar_extract_symlink(TAR *t, const char *realname);
|
||||
int tar_extract_chardev(TAR *t, const char *realname);
|
||||
int tar_extract_blockdev(TAR *t, const char *realname);
|
||||
int tar_extract_fifo(TAR *t, const char *realname);
|
||||
|
||||
/* for regfiles, we need to extract the content blocks as well */
|
||||
int tar_extract_regfile(TAR *t, char *realname, const int *progress_fd);
|
||||
int tar_extract_regfile(TAR *t, const char *realname, const int *progress_fd);
|
||||
int tar_skip_regfile(TAR *t);
|
||||
|
||||
/* extract regfile to buffer */
|
||||
int tar_extract_file_contents(TAR *t, void *buf, size_t *lenp);
|
||||
|
||||
/***** output.c ************************************************************/
|
||||
|
||||
@@ -280,16 +301,17 @@ int th_signed_crc_calc(TAR *t);
|
||||
#define th_crc_ok(t) (th_get_crc(t) == th_crc_calc(t) || th_get_crc(t) == th_signed_crc_calc(t))
|
||||
|
||||
/* string-octal to integer conversion */
|
||||
int oct_to_int(char *oct);
|
||||
int64_t oct_to_int(char *oct, size_t len);
|
||||
|
||||
/* string-octal or binary to integer conversion */
|
||||
int64_t oct_to_int_ex(char *oct, size_t len);
|
||||
|
||||
/* integer to NULL-terminated string-octal conversion */
|
||||
#define int_to_oct(num, oct, octlen) \
|
||||
snprintf((oct), (octlen), "%*lo ", (octlen) - 2, (unsigned long)(num))
|
||||
void int_to_oct(int64_t num, char *oct, size_t octlen);
|
||||
|
||||
/* integer to string-octal conversion, no NULL */
|
||||
void int_to_oct_nonull(int num, char *oct, size_t octlen);
|
||||
/* integer to string-octal conversion, or binary as necessary */
|
||||
void int_to_oct_ex(int64_t num, char *oct, size_t octlen);
|
||||
|
||||
#define tar_min(x, y) (x < y ? x : y)
|
||||
|
||||
/***** wrapper.c **********************************************************/
|
||||
|
||||
@@ -298,7 +320,7 @@ int tar_extract_glob(TAR *t, char *globname, char *prefix);
|
||||
int tar_extract_all(TAR *t, char *prefix, const int *progress_fd);
|
||||
|
||||
/* add a whole tree of files */
|
||||
int tar_append_tree(TAR *t, char *realdir, char *savedir, char *exclude);
|
||||
int tar_append_tree(TAR *t, char *realdir, char *savedir);
|
||||
|
||||
/* find an entry */
|
||||
int tar_find(TAR *t, char *searchstr);
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#ifndef libtar_LISTHASH_H
|
||||
#define libtar_LISTHASH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***** list.c **********************************************************/
|
||||
|
||||
@@ -192,5 +195,9 @@ int libtar_hash_add(libtar_hash_t *, void *);
|
||||
int libtar_hash_del(libtar_hash_t *,
|
||||
libtar_hashptr_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! libtar_LISTHASH_H */
|
||||
|
||||
|
||||
+4
-3
@@ -13,6 +13,7 @@
|
||||
#include <internal.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <time.h>
|
||||
@@ -83,14 +84,14 @@ th_print_long_ls(TAR *t)
|
||||
|
||||
uid = th_get_uid(t);
|
||||
pw = getpwuid(uid);
|
||||
if (pw == NULL)
|
||||
if ((t->options & TAR_USE_NUMERIC_ID) || pw == NULL)
|
||||
snprintf(username, sizeof(username), "%d", uid);
|
||||
else
|
||||
strlcpy(username, pw->pw_name, sizeof(username));
|
||||
|
||||
gid = th_get_gid(t);
|
||||
gr = getgrgid(gid);
|
||||
if (gr == NULL)
|
||||
if ((t->options & TAR_USE_NUMERIC_ID) || gr == NULL)
|
||||
snprintf(groupname, sizeof(groupname), "%d", gid);
|
||||
else
|
||||
strlcpy(groupname, gr->gr_name, sizeof(groupname));
|
||||
@@ -99,7 +100,7 @@ th_print_long_ls(TAR *t)
|
||||
printf("%.10s %-8.8s %-8.8s ", modestring, username, groupname);
|
||||
|
||||
if (TH_ISCHR(t) || TH_ISBLK(t))
|
||||
printf(" %3d, %3d ", th_get_devmajor(t), th_get_devminor(t));
|
||||
printf(" %3d, %3d ", (int)th_get_devmajor(t), (int)th_get_devminor(t));
|
||||
else
|
||||
printf("%9ld ", (long)th_get_size(t));
|
||||
|
||||
|
||||
+61
-14
@@ -126,7 +126,6 @@ th_crc_calc(TAR *t)
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
/* calculate a signed header checksum */
|
||||
int
|
||||
th_signed_crc_calc(TAR *t)
|
||||
@@ -141,25 +140,73 @@ th_signed_crc_calc(TAR *t)
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
/* string-octal to integer conversion */
|
||||
int
|
||||
oct_to_int(char *oct)
|
||||
int64_t
|
||||
oct_to_int(char *oct, size_t octlen)
|
||||
{
|
||||
int i;
|
||||
long long int val;
|
||||
char tmp[octlen + 1];
|
||||
|
||||
sscanf(oct, "%o", &i);
|
||||
|
||||
return i;
|
||||
memcpy(tmp, oct, octlen);
|
||||
tmp[octlen] = '\0';
|
||||
return sscanf(oct, "%llo", &val) == 1 ? (int64_t)val : 0;
|
||||
}
|
||||
|
||||
|
||||
/* integer to string-octal conversion, no NULL */
|
||||
/* string-octal or binary to integer conversion */
|
||||
int64_t oct_to_int_ex(char *oct, size_t octlen)
|
||||
{
|
||||
if (*(unsigned char *)oct & 0x80) {
|
||||
int64_t val = 0;
|
||||
char tmp[octlen];
|
||||
unsigned char *p;
|
||||
unsigned int i;
|
||||
|
||||
memcpy(tmp, oct, octlen);
|
||||
*tmp &= 0x7f;
|
||||
p = (unsigned char *)tmp + octlen - sizeof(val);
|
||||
for (i = 0; i < sizeof(val); ++i) {
|
||||
val <<= 8;
|
||||
val |= *(p++);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
return oct_to_int(oct, octlen);
|
||||
}
|
||||
|
||||
|
||||
/* integer to NULL-terminated string-octal conversion */
|
||||
void int_to_oct(int64_t num, char *oct, size_t octlen)
|
||||
{
|
||||
char tmp[sizeof(num)*3 + 1];
|
||||
int olen;
|
||||
|
||||
olen = sprintf(tmp, "%0*llo", (int)octlen, (long long)num);
|
||||
memcpy(oct, tmp + olen - octlen + 1, octlen);
|
||||
}
|
||||
|
||||
|
||||
/* integer to string-octal conversion, or binary as necessary */
|
||||
void
|
||||
int_to_oct_nonull(int num, char *oct, size_t octlen)
|
||||
int_to_oct_ex(int64_t num, char *oct, size_t octlen)
|
||||
{
|
||||
snprintf(oct, octlen, "%*lo", octlen - 1, (unsigned long)num);
|
||||
oct[octlen - 1] = ' ';
|
||||
if (num < 0 || num >= ((int64_t)1 << ((octlen - 1) * 3))) {
|
||||
unsigned char *p;
|
||||
unsigned int i;
|
||||
|
||||
memset(oct, 0, octlen);
|
||||
p = (unsigned char *)oct + octlen;
|
||||
for (i = 0; i < sizeof(num); ++i) {
|
||||
*(--p) = num & 0xff;
|
||||
num >>= 8;
|
||||
}
|
||||
if (num < 0) {
|
||||
for (; i < octlen; ++i) {
|
||||
*(--p) = 0xff;
|
||||
}
|
||||
}
|
||||
*(unsigned char *)oct |= 0x80;
|
||||
return;
|
||||
}
|
||||
int_to_oct(num, oct, octlen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+39
-71
@@ -10,18 +10,19 @@
|
||||
** University of Illinois at Urbana-Champaign
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
#include <internal.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
tar_extract_glob(TAR *t, char *globname, char *prefix)
|
||||
{
|
||||
@@ -44,7 +45,7 @@ tar_extract_glob(TAR *t, char *globname, char *prefix)
|
||||
snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
|
||||
else
|
||||
strlcpy(buf, filename, sizeof(buf));
|
||||
if (tar_extract_file(t, filename, prefix, &fd) != 0)
|
||||
if (tar_extract_file(t, buf, prefix, &fd) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -58,11 +59,12 @@ tar_extract_all(TAR *t, char *prefix, const int *progress_fd)
|
||||
char *filename;
|
||||
char buf[MAXPATHLEN];
|
||||
int i;
|
||||
printf("prefix: %s\n", prefix);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("==> tar_extract_all(TAR *t, \"%s\")\n",
|
||||
(prefix ? prefix : "(null)"));
|
||||
#endif
|
||||
|
||||
while ((i = th_read(t)) == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -79,105 +81,71 @@ tar_extract_all(TAR *t, char *prefix, const int *progress_fd)
|
||||
printf(" tar_extract_all(): calling tar_extract_file(t, "
|
||||
"\"%s\")\n", buf);
|
||||
#endif
|
||||
printf("item name: '%s'\n", filename);
|
||||
if (tar_extract_file(t, buf, prefix, progress_fd) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (i == 1 ? 0 : -1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
tar_append_tree(TAR *t, char *realdir, char *savedir, char *exclude)
|
||||
tar_append_tree(TAR *t, char *realdir, char *savedir)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("==> tar_append_tree(0x%lx, \"%s\", \"%s\")\n",
|
||||
(long unsigned int)t, realdir, (savedir ? savedir : "[NULL]"));
|
||||
#endif
|
||||
|
||||
char temp[1024];
|
||||
int skip = 0, i, n_spaces = 0;
|
||||
char ** excluded = NULL;
|
||||
char * p = NULL;
|
||||
if (exclude) {
|
||||
strcpy(temp, exclude);
|
||||
p = strtok(exclude, " ");
|
||||
if (p == NULL) {
|
||||
excluded = realloc(excluded, sizeof(char*) * (++n_spaces));
|
||||
excluded[0] = temp;
|
||||
} else {
|
||||
while (p) {
|
||||
excluded = realloc(excluded, sizeof(char*) * (++n_spaces));
|
||||
excluded[n_spaces-1] = p;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
excluded = realloc(excluded, sizeof(char*) * (n_spaces+1));
|
||||
excluded[n_spaces] = 0;
|
||||
for (i = 0; i < (n_spaces+1); i++) {
|
||||
if (realdir == excluded[i]) {
|
||||
printf(" excluding '%s'\n", excluded[i]);
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (skip == 0) {
|
||||
if (tar_append_file(t, realdir, savedir) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
char realpath[MAXPATHLEN];
|
||||
char savepath[MAXPATHLEN];
|
||||
struct dirent *dent;
|
||||
DIR *dp;
|
||||
struct stat s;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("==> tar_append_tree(0x%lx, \"%s\", \"%s\")\n",
|
||||
t, realdir, (savedir ? savedir : "[NULL]"));
|
||||
#endif
|
||||
|
||||
if (tar_append_file(t, realdir, savedir) != 0)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
puts(" tar_append_tree(): done with tar_append_file()...");
|
||||
#endif
|
||||
|
||||
dp = opendir(realdir);
|
||||
if (dp == NULL) {
|
||||
if (dp == NULL)
|
||||
{
|
||||
if (errno == ENOTDIR)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
while ((dent = readdir(dp)) != NULL) {
|
||||
if(strcmp(dent->d_name, ".") == 0
|
||||
|| strcmp(dent->d_name, "..") == 0)
|
||||
while ((dent = readdir(dp)) != NULL)
|
||||
{
|
||||
if (strcmp(dent->d_name, ".") == 0 ||
|
||||
strcmp(dent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
if (exclude) {
|
||||
int omit = 0;
|
||||
for (i = 0; i < (n_spaces+1); i++) {
|
||||
if (excluded[i] != NULL) {
|
||||
if (strcmp(dent->d_name, excluded[i]) == 0 || strcmp(excluded[i], realdir) == 0) {
|
||||
printf(" excluding '%s'\n", excluded[i]);
|
||||
omit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (omit)
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(realpath, MAXPATHLEN, "%s/%s", realdir, dent->d_name);
|
||||
snprintf(realpath, MAXPATHLEN, "%s/%s", realdir,
|
||||
dent->d_name);
|
||||
if (savedir)
|
||||
snprintf(savepath, MAXPATHLEN, "%s/%s", savedir, dent->d_name);
|
||||
snprintf(savepath, MAXPATHLEN, "%s/%s", savedir,
|
||||
dent->d_name);
|
||||
|
||||
if (lstat(realpath, &s) != 0)
|
||||
return -1;
|
||||
|
||||
if (S_ISDIR(s.st_mode)) {
|
||||
if (tar_append_tree(t, realpath, (savedir ? savepath : NULL), (exclude ? exclude : NULL)) != 0)
|
||||
return -1;
|
||||
continue;
|
||||
} else {
|
||||
if (tar_append_file(t, realpath, (savedir ? savepath : NULL)) != 0)
|
||||
if (S_ISDIR(s.st_mode))
|
||||
{
|
||||
if (tar_append_tree(t, realpath,
|
||||
(savedir ? savepath : NULL)) != 0)
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tar_append_file(t, realpath,
|
||||
(savedir ? savepath : NULL)) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
free(excluded);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user