This makes tar work perfectly, and adds in "--exclude" as an option

-Erik
This commit is contained in:
Erik Andersen 2000-04-09 15:17:40 +00:00
parent 84e09e4437
commit 0817d1372c
6 changed files with 247 additions and 177 deletions

View File

@ -11,16 +11,15 @@
patch your kernel with the devps patch in the kernel-patches/ patch your kernel with the devps patch in the kernel-patches/
directory. directory.
* Wrote basename, killall, and uptime. * Wrote basename, killall, and uptime.
* tar has been completely rewritten by me. Both tar creation and
extraction are now well behaved. Costs 7.6k with all optional
tar features enabled, and 5k for just tar extraction support.
* Added freeramdisk, which will free up all memory associated * Added freeramdisk, which will free up all memory associated
with a ram disk. Contributed by Emanuele Caratti <wiz@iol.it> with a ram disk. Contributed by Emanuele Caratti <wiz@iol.it>
and then adjusted a bit by me. and then adjusted a bit by me.
* Added tr and dirname from John Lombardo <john@deltanet.com> * Added tr and dirname from John Lombardo <john@deltanet.com>
* Added echo and test (from me). * Added echo and test (from me).
* Added usleep contributed by Nicolas Pitre <nico@cam.org> * Added usleep contributed by Nicolas Pitre <nico@cam.org>
* tar wouldn't create directory entries that don't end in '/',
now it does (thanks to Avery Pennarun <apenwarr@worldvisions.ca>)
* tar has been completely rewritten, and tar creation and extraction
is now much better behaved.
* Several fixes from Pavel Roskin <pavel_roskin@geocities.com>: * Several fixes from Pavel Roskin <pavel_roskin@geocities.com>:
- When `tail' fails to open a file it now exits. - When `tail' fails to open a file it now exits.
- When `syslogd' is given the `-n' option it should still use - When `syslogd' is given the `-n' option it should still use

View File

@ -25,7 +25,7 @@ BUILDTIME := $(shell TZ=UTC date --utc "+%Y.%m.%d-%H:%M%z")
# Set the following to `true' to make a debuggable build. # Set the following to `true' to make a debuggable build.
# Leave this set to `false' for production use. # Leave this set to `false' for production use.
# eg: `make DODEBUG=true tests' # eg: `make DODEBUG=true tests'
DODEBUG = true DODEBUG = false
# If you want a static binary, turn this on. I can't think # If you want a static binary, turn this on. I can't think
# of many situations where anybody would ever want it static, # of many situations where anybody would ever want it static,
@ -72,7 +72,7 @@ endif
# -D_GNU_SOURCE is needed because environ is used in init.c # -D_GNU_SOURCE is needed because environ is used in init.c
ifeq ($(DODEBUG),true) ifeq ($(DODEBUG),true)
CFLAGS += -Wall -g -D_GNU_SOURCE CFLAGS += -Wall -g -D_GNU_SOURCE
LDFLAGS = LDFLAGS =
STRIP = STRIP =
else else
CFLAGS += -Wall $(OPTIMIZATION) -fomit-frame-pointer -fno-builtin -D_GNU_SOURCE CFLAGS += -Wall $(OPTIMIZATION) -fomit-frame-pointer -fno-builtin -D_GNU_SOURCE

8
TODO
View File

@ -22,7 +22,7 @@ around to it some time. If you have any good ideas, please let me know.
* hwclock * hwclock
* stty * stty
* cut * cut
* expr (maybe?) (ash builtin?) * expr
@ -42,12 +42,6 @@ Perhaps I need to add a better build system (like the Linux kernel?)
----------------------- -----------------------
There is no exclude file(s) option to tar. LRP's packaging system can not
function without this. Will you have the time to add this soon?
-----------------------
Feature request: Feature request:
/bin/busybox --install -s which makes all links to commands that it /bin/busybox --install -s which makes all links to commands that it

View File

@ -52,33 +52,33 @@
#include <sys/param.h> /* for PATH_MAX */ #include <sys/param.h> /* for PATH_MAX */
static const char tar_usage[] =
#ifdef BB_FEATURE_TAR_CREATE #ifdef BB_FEATURE_TAR_CREATE
"tar -[cxtvO] "
static const char tar_usage[] =
"tar -[cxtvOf] [tarFile] [-X excludeFile] [FILE] ...\n\n"
"Create, extract, or list files from a tar file. Note that\n"
"this version of tar packs hard links as separate files.\n\n"
"Options:\n"
"\tc=create, x=extract, t=list contents, v=verbose,\n"
"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"
"\tX=exclude file\n";
#else #else
"tar -[xtvO] "
static const char tar_usage[] =
"tar -[xtvO] [-f tarFile] [-X excludeFile] [FILE] ...\n\n"
"Extract, or list files stored in a tar file. This\n"
"version of tar does not support creation of tar files.\n\n"
"Options:\n"
"\tx=extract, t=list contents, v=verbose,\n"
"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"
"\tX=exclude file\n";
#endif #endif
#if defined BB_FEATURE_TAR_EXCLUDE
"[--exclude File] "
#endif
"[-f tarFile] [FILE] ...\n\n"
"Create, extract, or list files from a tar file. Note that\n"
"this version of tar treats hard links as separate files.\n\n"
"Main operation mode:\n"
#ifdef BB_FEATURE_TAR_CREATE
"\tc\t\tcreate\n"
#endif
"\tx\t\textract\n"
"\tt\t\tlist\n"
"File selection:\n"
"\tf\t\tname of tarfile or \"-\" for stdin\n"
"\tO\t\textract to stdout\n"
#if defined BB_FEATURE_TAR_EXCLUDE
"\t--exclude\tfile to exclude\n"
#endif
"Informative output:\n"
"\tv\t\tverbosely list files processed\n"
;
/* Tar file constants */ /* Tar file constants */
#ifndef MAJOR #ifndef MAJOR
@ -91,31 +91,30 @@ static const char tar_usage[] =
struct TarHeader struct TarHeader
{ {
/* byte offset */ /* byte offset */
char name[100]; /* 0 */ char name[100]; /* 0-99 */
char mode[8]; /* 100 */ char mode[8]; /* 100-107 */
char uid[8]; /* 108 */ char uid[8]; /* 108-115 */
char gid[8]; /* 116 */ char gid[8]; /* 116-123 */
char size[12]; /* 124 */ char size[12]; /* 124-135 */
char mtime[12]; /* 136 */ char mtime[12]; /* 136-147 */
char chksum[8]; /* 148 */ char chksum[8]; /* 148-155 */
char typeflag; /* 156 */ char typeflag; /* 156-156 */
char linkname[100]; /* 157 */ char linkname[100]; /* 157-256 */
char magic[6]; /* 257 */ char magic[6]; /* 257-262 */
char version[2]; /* 263 */ char version[2]; /* 263-264 */
char uname[32]; /* 265 */ char uname[32]; /* 265-296 */
char gname[32]; /* 297 */ char gname[32]; /* 297-328 */
char devmajor[8]; /* 329 */ char devmajor[8]; /* 329-336 */
char devminor[8]; /* 337 */ char devminor[8]; /* 337-344 */
char prefix[155]; /* 345 */ char prefix[155]; /* 345-499 */
/* padding 500 */ char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */
}; };
typedef struct TarHeader TarHeader; typedef struct TarHeader TarHeader;
/* A few useful constants */ /* A few useful constants */
#define TAR_MAGIC "ustar" /* ustar and a null */ #define TAR_MAGIC "ustar" /* ustar and a null */
//#define TAR_VERSION "00" /* 00 and no null */ #define TAR_VERSION " " /* Be compatable with GNU tar format */
#define TAR_VERSION " " /* Be compatable with old GNU format */
#define TAR_MAGIC_LEN 6 #define TAR_MAGIC_LEN 6
#define TAR_VERSION_LEN 2 #define TAR_VERSION_LEN 2
#define TAR_BLOCK_SIZE 512 #define TAR_BLOCK_SIZE 512
@ -170,7 +169,9 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
extern int tar_main(int argc, char **argv) extern int tar_main(int argc, char **argv)
{ {
char** excludeList=NULL; char** excludeList=NULL;
#if defined BB_FEATURE_TAR_EXCLUDE
int excludeListSize=0; int excludeListSize=0;
#endif
const char *tarName=NULL; const char *tarName=NULL;
int listFlag = FALSE; int listFlag = FALSE;
int extractFlag = FALSE; int extractFlag = FALSE;
@ -224,22 +225,26 @@ extern int tar_main(int argc, char **argv)
tostdoutFlag = TRUE; tostdoutFlag = TRUE;
tarName = "-"; tarName = "-";
break; break;
case 'X':
if (--argc == 0) {
fatalError( "Option requires an argument: No file specified\n");
}
excludeList=realloc( excludeList, sizeof(char**) * (excludeListSize+1));
excludeList[excludeListSize] = *(++argv);
/* Remove leading "/"s */
if (*excludeList[excludeListSize] =='/') {
excludeList[excludeListSize] = (excludeList[excludeListSize])+1;
}
if (excludeList[excludeListSize++] == NULL)
fatalError( "Option requires an argument: No file specified\n");
stopIt=TRUE;
break;
case '-': case '-':
#if defined BB_FEATURE_TAR_EXCLUDE
if (strcmp(*argv, "-exclude")==0) {
if (--argc == 0) {
fatalError( "Option requires an argument: No file specified\n");
}
excludeList=realloc( excludeList, sizeof(char**) * (excludeListSize+2));
excludeList[excludeListSize] = *(++argv);
/* Remove leading "/"s */
if (*excludeList[excludeListSize] =='/') {
excludeList[excludeListSize] = (excludeList[excludeListSize])+1;
}
if (excludeList[excludeListSize++] == NULL)
fatalError( "Option requires an argument: No file specified\n");
/* Tack a NULL onto the end of the list */
excludeList[excludeListSize] = NULL;
stopIt=TRUE;
break;
}
#endif
usage(tar_usage); usage(tar_usage);
break; break;
@ -249,13 +254,6 @@ extern int tar_main(int argc, char **argv)
} }
} }
} }
#if 0
for (i=0; i<excludeListSize; i++) {
printf( "%s\n", excludeList[i]);
fflush(stdout);
}
#endif
/* /*
* Do the correct type of action supplying the rest of the * Do the correct type of action supplying the rest of the
@ -336,6 +334,8 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag)
errorMsg(io_error, header->name, strerror(errno)); errorMsg(io_error, header->name, strerror(errno));
return( FALSE); return( FALSE);
} }
} else {
actualWriteSz=writeSize;
} }
size -= actualWriteSz; size -= actualWriteSz;
@ -532,11 +532,13 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
static int readTarFile(const char* tarName, int extractFlag, int listFlag, static int readTarFile(const char* tarName, int extractFlag, int listFlag,
int tostdoutFlag, int verboseFlag, char** excludeList) int tostdoutFlag, int verboseFlag, char** excludeList)
{ {
int status, tarFd=0; int status, tarFd=-1;
int errorFlag=FALSE; int errorFlag=FALSE;
TarHeader rawHeader; TarHeader rawHeader;
TarInfo header; TarInfo header;
//int skipFileFlag=FALSE; #if defined BB_FEATURE_TAR_EXCLUDE
char** tmpList;
#endif
/* Open the tar file for reading. */ /* Open the tar file for reading. */
if (!strcmp(tarName, "-")) if (!strcmp(tarName, "-"))
@ -557,7 +559,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
/* First, try to read the header */ /* First, try to read the header */
if ( readTarHeader(&rawHeader, &header) == FALSE ) { if ( readTarHeader(&rawHeader, &header) == FALSE ) {
close( tarFd);
if ( *(header.name) == '\0' ) { if ( *(header.name) == '\0' ) {
goto endgame; goto endgame;
} else { } else {
@ -568,7 +569,34 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
} }
if ( *(header.name) == '\0' ) if ( *(header.name) == '\0' )
goto endgame; goto endgame;
header.tarFd = tarFd;
#if defined BB_FEATURE_TAR_EXCLUDE
{
int skipFlag=FALSE;
/* Check for excluded files.... */
for (tmpList=excludeList; tmpList && *tmpList; tmpList++) {
/* Do some extra hoop jumping for when directory names
* end in '/' but the entry in tmpList doesn't */
if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || (
header.name[strlen(header.name)-1]=='/'
&& strncmp( *tmpList, header.name,
MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) {
/* If it is a regular file, pretend to extract it with
* the extractFlag set to FALSE, so the junk in the tarball
* is properly skipped over */
if ( header.type==REGTYPE || header.type==REGTYPE0 ) {
tarExtractRegularFile(&header, FALSE, FALSE);
}
skipFlag=TRUE;
break;
}
}
/* There are not the droids you're looking for, move along */
if (skipFlag==TRUE)
continue;
}
#endif
/* Special treatment if the list (-t) flag is on */ /* Special treatment if the list (-t) flag is on */
if (verboseFlag == TRUE && extractFlag == FALSE) { if (verboseFlag == TRUE && extractFlag == FALSE) {
int len, len1; int len, len1;
@ -623,13 +651,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
printf("\n"); printf("\n");
} }
#if 0
/* See if we want to restore this file or not */
skipFileFlag=FALSE;
if (wantFileName(outName) == FALSE) {
skipFileFlag = TRUE;
}
#endif
/* Remove any clutter lying in our way */ /* Remove any clutter lying in our way */
unlink( header.name); unlink( header.name);
@ -751,7 +772,9 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
{ {
long chksum=0; long chksum=0;
struct TarHeader header; struct TarHeader header;
#if defined BB_FEATURE_TAR_EXCLUDE
char** tmpList; char** tmpList;
#endif
const unsigned char *cp = (const unsigned char *) &header; const unsigned char *cp = (const unsigned char *) &header;
ssize_t size = sizeof(struct TarHeader); ssize_t size = sizeof(struct TarHeader);
@ -769,15 +792,23 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
strncpy(header.name, fileName, sizeof(header.name)); strncpy(header.name, fileName, sizeof(header.name));
} }
/* Now that leading '/''s have been removed, #if defined BB_FEATURE_TAR_EXCLUDE
* check for excluded files.... */ /* Check for excluded files.... */
for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) {
printf( "comparing '%s' and '%s'", *tmpList, header.name); /* Do some extra hoop jumping for when directory names
if (strcmp( *tmpList, header.name)==0) * end in '/' but the entry in tmpList doesn't */
printf( ": match\n"); if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || (
else header.name[strlen(header.name)-1]=='/'
printf( "\n"); && strncmp( *tmpList, header.name,
MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) {
/* Set the mode to something that is not a regular file, thereby
* faking out writeTarFile into thinking that nothing further need
* be done for this file. Yes, I know this is ugly, but it works. */
statbuf->st_mode = 0;
return( TRUE);
}
} }
#endif
putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
@ -965,6 +996,12 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
for (size=0; size<(2*TAR_BLOCK_SIZE); size++) { for (size=0; size<(2*TAR_BLOCK_SIZE); size++) {
write(tbInfo.tarFd, "\0", 1); write(tbInfo.tarFd, "\0", 1);
} }
/* To be pedantically correct, we would check if the tarball
* is smaller then 20 tar blocks, and pad it if it was smaller,
* but that isn't necessary for GNU tar interoperability, and
* so is considered a waste of space */
/* Hang up the tools, close up shop, head home */ /* Hang up the tools, close up shop, head home */
close(tarFd); close(tarFd);
if (errorFlag == TRUE) { if (errorFlag == TRUE) {

View File

@ -180,6 +180,9 @@
// Enable support for creation of tar files. // Enable support for creation of tar files.
#define BB_FEATURE_TAR_CREATE #define BB_FEATURE_TAR_CREATE
// //
// Enable support for "--exclude" for excluding files
//#define BB_FEATURE_TAR_EXCLUDE
//
//// Enable reverse sort //// Enable reverse sort
//#define BB_FEATURE_SORT_REVERSE //#define BB_FEATURE_SORT_REVERSE
// //

201
tar.c
View File

@ -52,33 +52,33 @@
#include <sys/param.h> /* for PATH_MAX */ #include <sys/param.h> /* for PATH_MAX */
static const char tar_usage[] =
#ifdef BB_FEATURE_TAR_CREATE #ifdef BB_FEATURE_TAR_CREATE
"tar -[cxtvO] "
static const char tar_usage[] =
"tar -[cxtvOf] [tarFile] [-X excludeFile] [FILE] ...\n\n"
"Create, extract, or list files from a tar file. Note that\n"
"this version of tar packs hard links as separate files.\n\n"
"Options:\n"
"\tc=create, x=extract, t=list contents, v=verbose,\n"
"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"
"\tX=exclude file\n";
#else #else
"tar -[xtvO] "
static const char tar_usage[] =
"tar -[xtvO] [-f tarFile] [-X excludeFile] [FILE] ...\n\n"
"Extract, or list files stored in a tar file. This\n"
"version of tar does not support creation of tar files.\n\n"
"Options:\n"
"\tx=extract, t=list contents, v=verbose,\n"
"\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"
"\tX=exclude file\n";
#endif #endif
#if defined BB_FEATURE_TAR_EXCLUDE
"[--exclude File] "
#endif
"[-f tarFile] [FILE] ...\n\n"
"Create, extract, or list files from a tar file. Note that\n"
"this version of tar treats hard links as separate files.\n\n"
"Main operation mode:\n"
#ifdef BB_FEATURE_TAR_CREATE
"\tc\t\tcreate\n"
#endif
"\tx\t\textract\n"
"\tt\t\tlist\n"
"File selection:\n"
"\tf\t\tname of tarfile or \"-\" for stdin\n"
"\tO\t\textract to stdout\n"
#if defined BB_FEATURE_TAR_EXCLUDE
"\t--exclude\tfile to exclude\n"
#endif
"Informative output:\n"
"\tv\t\tverbosely list files processed\n"
;
/* Tar file constants */ /* Tar file constants */
#ifndef MAJOR #ifndef MAJOR
@ -91,31 +91,30 @@ static const char tar_usage[] =
struct TarHeader struct TarHeader
{ {
/* byte offset */ /* byte offset */
char name[100]; /* 0 */ char name[100]; /* 0-99 */
char mode[8]; /* 100 */ char mode[8]; /* 100-107 */
char uid[8]; /* 108 */ char uid[8]; /* 108-115 */
char gid[8]; /* 116 */ char gid[8]; /* 116-123 */
char size[12]; /* 124 */ char size[12]; /* 124-135 */
char mtime[12]; /* 136 */ char mtime[12]; /* 136-147 */
char chksum[8]; /* 148 */ char chksum[8]; /* 148-155 */
char typeflag; /* 156 */ char typeflag; /* 156-156 */
char linkname[100]; /* 157 */ char linkname[100]; /* 157-256 */
char magic[6]; /* 257 */ char magic[6]; /* 257-262 */
char version[2]; /* 263 */ char version[2]; /* 263-264 */
char uname[32]; /* 265 */ char uname[32]; /* 265-296 */
char gname[32]; /* 297 */ char gname[32]; /* 297-328 */
char devmajor[8]; /* 329 */ char devmajor[8]; /* 329-336 */
char devminor[8]; /* 337 */ char devminor[8]; /* 337-344 */
char prefix[155]; /* 345 */ char prefix[155]; /* 345-499 */
/* padding 500 */ char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */
}; };
typedef struct TarHeader TarHeader; typedef struct TarHeader TarHeader;
/* A few useful constants */ /* A few useful constants */
#define TAR_MAGIC "ustar" /* ustar and a null */ #define TAR_MAGIC "ustar" /* ustar and a null */
//#define TAR_VERSION "00" /* 00 and no null */ #define TAR_VERSION " " /* Be compatable with GNU tar format */
#define TAR_VERSION " " /* Be compatable with old GNU format */
#define TAR_MAGIC_LEN 6 #define TAR_MAGIC_LEN 6
#define TAR_VERSION_LEN 2 #define TAR_VERSION_LEN 2
#define TAR_BLOCK_SIZE 512 #define TAR_BLOCK_SIZE 512
@ -170,7 +169,9 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
extern int tar_main(int argc, char **argv) extern int tar_main(int argc, char **argv)
{ {
char** excludeList=NULL; char** excludeList=NULL;
#if defined BB_FEATURE_TAR_EXCLUDE
int excludeListSize=0; int excludeListSize=0;
#endif
const char *tarName=NULL; const char *tarName=NULL;
int listFlag = FALSE; int listFlag = FALSE;
int extractFlag = FALSE; int extractFlag = FALSE;
@ -224,22 +225,26 @@ extern int tar_main(int argc, char **argv)
tostdoutFlag = TRUE; tostdoutFlag = TRUE;
tarName = "-"; tarName = "-";
break; break;
case 'X':
if (--argc == 0) {
fatalError( "Option requires an argument: No file specified\n");
}
excludeList=realloc( excludeList, sizeof(char**) * (excludeListSize+1));
excludeList[excludeListSize] = *(++argv);
/* Remove leading "/"s */
if (*excludeList[excludeListSize] =='/') {
excludeList[excludeListSize] = (excludeList[excludeListSize])+1;
}
if (excludeList[excludeListSize++] == NULL)
fatalError( "Option requires an argument: No file specified\n");
stopIt=TRUE;
break;
case '-': case '-':
#if defined BB_FEATURE_TAR_EXCLUDE
if (strcmp(*argv, "-exclude")==0) {
if (--argc == 0) {
fatalError( "Option requires an argument: No file specified\n");
}
excludeList=realloc( excludeList, sizeof(char**) * (excludeListSize+2));
excludeList[excludeListSize] = *(++argv);
/* Remove leading "/"s */
if (*excludeList[excludeListSize] =='/') {
excludeList[excludeListSize] = (excludeList[excludeListSize])+1;
}
if (excludeList[excludeListSize++] == NULL)
fatalError( "Option requires an argument: No file specified\n");
/* Tack a NULL onto the end of the list */
excludeList[excludeListSize] = NULL;
stopIt=TRUE;
break;
}
#endif
usage(tar_usage); usage(tar_usage);
break; break;
@ -249,13 +254,6 @@ extern int tar_main(int argc, char **argv)
} }
} }
} }
#if 0
for (i=0; i<excludeListSize; i++) {
printf( "%s\n", excludeList[i]);
fflush(stdout);
}
#endif
/* /*
* Do the correct type of action supplying the rest of the * Do the correct type of action supplying the rest of the
@ -336,6 +334,8 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag)
errorMsg(io_error, header->name, strerror(errno)); errorMsg(io_error, header->name, strerror(errno));
return( FALSE); return( FALSE);
} }
} else {
actualWriteSz=writeSize;
} }
size -= actualWriteSz; size -= actualWriteSz;
@ -532,11 +532,13 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
static int readTarFile(const char* tarName, int extractFlag, int listFlag, static int readTarFile(const char* tarName, int extractFlag, int listFlag,
int tostdoutFlag, int verboseFlag, char** excludeList) int tostdoutFlag, int verboseFlag, char** excludeList)
{ {
int status, tarFd=0; int status, tarFd=-1;
int errorFlag=FALSE; int errorFlag=FALSE;
TarHeader rawHeader; TarHeader rawHeader;
TarInfo header; TarInfo header;
//int skipFileFlag=FALSE; #if defined BB_FEATURE_TAR_EXCLUDE
char** tmpList;
#endif
/* Open the tar file for reading. */ /* Open the tar file for reading. */
if (!strcmp(tarName, "-")) if (!strcmp(tarName, "-"))
@ -557,7 +559,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
/* First, try to read the header */ /* First, try to read the header */
if ( readTarHeader(&rawHeader, &header) == FALSE ) { if ( readTarHeader(&rawHeader, &header) == FALSE ) {
close( tarFd);
if ( *(header.name) == '\0' ) { if ( *(header.name) == '\0' ) {
goto endgame; goto endgame;
} else { } else {
@ -568,7 +569,34 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
} }
if ( *(header.name) == '\0' ) if ( *(header.name) == '\0' )
goto endgame; goto endgame;
header.tarFd = tarFd;
#if defined BB_FEATURE_TAR_EXCLUDE
{
int skipFlag=FALSE;
/* Check for excluded files.... */
for (tmpList=excludeList; tmpList && *tmpList; tmpList++) {
/* Do some extra hoop jumping for when directory names
* end in '/' but the entry in tmpList doesn't */
if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || (
header.name[strlen(header.name)-1]=='/'
&& strncmp( *tmpList, header.name,
MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) {
/* If it is a regular file, pretend to extract it with
* the extractFlag set to FALSE, so the junk in the tarball
* is properly skipped over */
if ( header.type==REGTYPE || header.type==REGTYPE0 ) {
tarExtractRegularFile(&header, FALSE, FALSE);
}
skipFlag=TRUE;
break;
}
}
/* There are not the droids you're looking for, move along */
if (skipFlag==TRUE)
continue;
}
#endif
/* Special treatment if the list (-t) flag is on */ /* Special treatment if the list (-t) flag is on */
if (verboseFlag == TRUE && extractFlag == FALSE) { if (verboseFlag == TRUE && extractFlag == FALSE) {
int len, len1; int len, len1;
@ -623,13 +651,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
printf("\n"); printf("\n");
} }
#if 0
/* See if we want to restore this file or not */
skipFileFlag=FALSE;
if (wantFileName(outName) == FALSE) {
skipFileFlag = TRUE;
}
#endif
/* Remove any clutter lying in our way */ /* Remove any clutter lying in our way */
unlink( header.name); unlink( header.name);
@ -751,7 +772,9 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
{ {
long chksum=0; long chksum=0;
struct TarHeader header; struct TarHeader header;
#if defined BB_FEATURE_TAR_EXCLUDE
char** tmpList; char** tmpList;
#endif
const unsigned char *cp = (const unsigned char *) &header; const unsigned char *cp = (const unsigned char *) &header;
ssize_t size = sizeof(struct TarHeader); ssize_t size = sizeof(struct TarHeader);
@ -769,15 +792,23 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
strncpy(header.name, fileName, sizeof(header.name)); strncpy(header.name, fileName, sizeof(header.name));
} }
/* Now that leading '/''s have been removed, #if defined BB_FEATURE_TAR_EXCLUDE
* check for excluded files.... */ /* Check for excluded files.... */
for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) {
printf( "comparing '%s' and '%s'", *tmpList, header.name); /* Do some extra hoop jumping for when directory names
if (strcmp( *tmpList, header.name)==0) * end in '/' but the entry in tmpList doesn't */
printf( ": match\n"); if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || (
else header.name[strlen(header.name)-1]=='/'
printf( "\n"); && strncmp( *tmpList, header.name,
MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) {
/* Set the mode to something that is not a regular file, thereby
* faking out writeTarFile into thinking that nothing further need
* be done for this file. Yes, I know this is ugly, but it works. */
statbuf->st_mode = 0;
return( TRUE);
}
} }
#endif
putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
@ -965,6 +996,12 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
for (size=0; size<(2*TAR_BLOCK_SIZE); size++) { for (size=0; size<(2*TAR_BLOCK_SIZE); size++) {
write(tbInfo.tarFd, "\0", 1); write(tbInfo.tarFd, "\0", 1);
} }
/* To be pedantically correct, we would check if the tarball
* is smaller then 20 tar blocks, and pad it if it was smaller,
* but that isn't necessary for GNU tar interoperability, and
* so is considered a waste of space */
/* Hang up the tools, close up shop, head home */ /* Hang up the tools, close up shop, head home */
close(tarFd); close(tarFd);
if (errorFlag == TRUE) { if (errorFlag == TRUE) {