This makes tar work perfectly, and adds in "--exclude" as an option
-Erik
This commit is contained in:
parent
84e09e4437
commit
0817d1372c
@ -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
|
||||||
|
4
Makefile
4
Makefile
@ -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
8
TODO
@ -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
|
||||||
|
201
archival/tar.c
201
archival/tar.c
@ -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) {
|
||||||
|
@ -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
201
tar.c
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user