Update tar so creation of tarballs is much closer to working...

-Erik
This commit is contained in:
Erik Andersen 2000-04-04 18:39:50 +00:00
parent 183da4ade1
commit 68a9ea4208
2 changed files with 250 additions and 136 deletions

View File

@ -1,12 +1,12 @@
/* vi: set sw=4 ts=4: */ /* vi: set sw=4 ts=4: */
/* /*
* Mini tar implementation for busybox
* *
* Mini tar implementation for busybox Note, that as of BusyBox 0.43 tar has * Note, that as of BusyBox 0.43 tar has been completely rewritten from the
* been completely rewritten from the ground up. It still has remnents of the * ground up. It still has remnents of the old code lying about, but it pretty
* old code lying about, but it pretty different (i.e. cleaner, less global * different (i.e. cleaner, less global variables, etc)
* variables, etc)
* *
* Copyright (C) 1999 by Lineo, inc. * Copyright (C) 2000 by Lineo, inc.
* Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
* *
* Based in part in the tar implementation in sash * Based in part in the tar implementation in sash
@ -15,7 +15,7 @@
* provided that this copyright notice remains intact. * provided that this copyright notice remains intact.
* Permission to distribute sash derived code under the GPL has been granted. * Permission to distribute sash derived code under the GPL has been granted.
* *
* Based in part on the tar implementation in busybox-0.28 * Based in part on the tar implementation from busybox-0.28
* Copyright (C) 1995 Bruce Perens * Copyright (C) 1995 Bruce Perens
* This is free software under the GNU General Public License. * This is free software under the GNU General Public License.
* *
@ -162,8 +162,8 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
#ifdef BB_FEATURE_TAR_CREATE #ifdef BB_FEATURE_TAR_CREATE
/* Local procedures to save files into a tar file. */ /* Local procedures to save files into a tar file. */
static int writeTarFile(const char* tarName, int extractFlag, int listFlag, static int writeTarFile(const char* tarName, int tostdoutFlag,
int tostdoutFlag, int verboseFlag, int argc, char **argv); int verboseFlag, int argc, char **argv);
static int putOctal(char *cp, int len, long value); static int putOctal(char *cp, int len, long value);
#endif #endif
@ -249,7 +249,7 @@ extern int tar_main(int argc, char **argv)
#ifndef BB_FEATURE_TAR_CREATE #ifndef BB_FEATURE_TAR_CREATE
fatalError( "This version of tar was not compiled with tar creation support.\n"); fatalError( "This version of tar was not compiled with tar creation support.\n");
#else #else
exit(writeTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag, argc, argv)); exit(writeTarFile(tarName, tostdoutFlag, verboseFlag, argc, argv));
#endif #endif
} else { } else {
exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag)); exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag));
@ -410,8 +410,6 @@ tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag)
mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)); mknod(header->name, header->mode, makedev(header->devmajor, header->devminor));
} else if (S_ISFIFO(header->mode)) { } else if (S_ISFIFO(header->mode)) {
mkfifo(header->name, header->mode); mkfifo(header->name, header->mode);
} else {
open(header->name, O_WRONLY | O_CREAT | O_TRUNC, header->mode);
} }
/* Now set permissions etc for the new directory */ /* Now set permissions etc for the new directory */
@ -625,6 +623,21 @@ endgame:
#ifdef BB_FEATURE_TAR_CREATE #ifdef BB_FEATURE_TAR_CREATE
/* Some info to be carried along when creating a new tarball */
struct TarBallInfo
{
char* fileName; /* File name of the tarball */
int tarFd; /* Open-for-write file descriptor
for the tarball */
struct stat statBuf; /* Stat info for the tarball, letting
us know the inode and device that the
tarball lives, so we can avoid trying
to include the tarball into itself */
int verboseFlag; /* Whether to print extra stuff or not */
};
typedef struct TarBallInfo TarBallInfo;
/* Put an octal string into the specified buffer. /* Put an octal string into the specified buffer.
* The number is zero and space padded and possibly null padded. * The number is zero and space padded and possibly null padded.
* Returns TRUE if successful. */ * Returns TRUE if successful. */
@ -662,41 +675,55 @@ static int putOctal (char *cp, int len, long value)
return TRUE; return TRUE;
} }
/* Write out a tar header for the specified file */ /* Write out a tar header for the specified file/directory/whatever */
static int static int
writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf)
{ {
int i; //int i;
long chksum, sum; //long chksum, sum;
unsigned char *s = (unsigned char *)rawHeader;
struct TarHeader header; if (*fileName=='/') {
static int alreadyWarned=FALSE;
strcpy(header.name, fileName); if (alreadyWarned==FALSE) {
putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777); errorMsg("tar: Removing leading '/' from member names\n");
putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); alreadyWarned=TRUE;
putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
putOctal(header.size, sizeof(header.size), statbuf->st_size);
putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
if (S_ISLNK(statbuf.st_mode)) {
header.type = LNKTYPE;
// Handle SYMTYPE
} else if (S_ISDIR(statbuf.st_mode)) {
header.type = DIRTYPE;
} else if (S_ISCHR(statbuf.st_mode)) {
header.type = CHRTYPE;
} else if (S_ISBLK(statbuf.st_mode)) {
header.type = BLKTYPE;
} else if (S_ISFIFO(statbuf.st_mode)) {
header.type = FIFOTYPE;
} else if (S_ISSOCK(statbuf.st_mode)) {
header.type = S_ISSOCK;
} else if (S_ISLNK(statbuf.st_mode)) {
header.type = LNKTYPE;
} else if (S_ISLNK(statbuf.st_mode)) {
header.type = REGTYPE;
} }
strcpy(header->name, fileName+1);
}
else {
strcpy(header->name, fileName);
}
putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777);
putOctal(header->uid, sizeof(header->uid), statbuf->st_uid);
putOctal(header->gid, sizeof(header->gid), statbuf->st_gid);
putOctal(header->size, sizeof(header->size), statbuf->st_size);
putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime);
if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = LNKTYPE;
// TODO -- Handle SYMTYPE
} else if (S_ISDIR(statbuf->st_mode)) {
header->typeflag = DIRTYPE;
strncat(header->name, "/", sizeof(header->name));
} else if (S_ISCHR(statbuf->st_mode)) {
header->typeflag = CHRTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
} else if (S_ISBLK(statbuf->st_mode)) {
header->typeflag = BLKTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
} else if (S_ISFIFO(statbuf->st_mode)) {
header->typeflag = FIFOTYPE;
} else if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = LNKTYPE;
} else if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = REGTYPE;
} else {
return ( FALSE);
}
return ( TRUE);
#if 0 #if 0
header->linkname = rawHeader->linkname; header->linkname = rawHeader->linkname;
header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
@ -704,31 +731,58 @@ writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
/* Write out the checksum */ /* Write out the checksum */
chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
return ( TRUE);
#endif #endif
return ( TRUE);
} }
static int fileAction(const char *fileName, struct stat *statbuf, void* userData) static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
{ {
int *tarFd=(int*)userData; int inputFileFd;
dprintf(*tarFd, "%s\n", fileName); struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
char header[sizeof(struct TarHeader)];
/* First open the file we want to archive, and make sure all is well */
if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
return( TRUE); return( TRUE);
} }
static int writeTarFile(const char* tarName, int extractFlag, int listFlag, /* It is against the rules to archive a socket */
int tostdoutFlag, int verboseFlag, int argc, char **argv) if (S_ISSOCK(statbuf->st_mode)) {
errorMsg("tar: %s: socket ignored\n", fileName);
return( TRUE);
}
/* It is a bad idea to store the archive we are in the process of creating,
* so check the device and inode to be sure that this particular file isn't
* the new tarball */
if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
tbInfo->statBuf.st_ino == statbuf->st_ino) {
errorMsg("tar: %s: file is the archive; skipping\n", fileName);
return( TRUE);
}
memset( header, 0, sizeof(struct TarHeader));
if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) {
dprintf(tbInfo->tarFd, "%s", header);
}
/* Now do the verbose thing (or not) */
if (tbInfo->verboseFlag==TRUE)
fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name);
return( TRUE);
}
static int writeTarFile(const char* tarName, int tostdoutFlag,
int verboseFlag, int argc, char **argv)
{ {
int tarFd=-1; int tarFd=-1;
//int errorFlag=FALSE; int errorFlag=FALSE;
//TarHeader rawHeader;
//TarInfo header;
//int alreadyWarned=FALSE;
//int skipFileFlag=FALSE; //int skipFileFlag=FALSE;
struct stat tarballStat; struct TarBallInfo tbInfo;
dev_t tarDev = 0; tbInfo.verboseFlag = verboseFlag;
ino_t tarInode = 0;
/* Make sure there is at least one file to tar up. */ /* Make sure there is at least one file to tar up. */
if (argc <= 0) if (argc <= 0)
@ -736,19 +790,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
/* Open the tar file for writing. */ /* Open the tar file for writing. */
if (tostdoutFlag == TRUE) if (tostdoutFlag == TRUE)
tarFd = fileno(stdout); tbInfo.tarFd = fileno(stdout);
else else
tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644); tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (tarFd < 0) { if (tbInfo.tarFd < 0) {
errorMsg( "Error opening '%s': %s\n", tarName, strerror(errno)); errorMsg( "tar: Error opening '%s': %s\n", tarName, strerror(errno));
return ( FALSE); return ( FALSE);
} }
/* Store the device and inode of the tarball, so we can be sure /* Store the stat info for the tarball's file, so
* not to try and include it into itself.... */ * can avoid including the tarball into itself.... */
if (fstat(tarFd, &tarballStat) < 0) if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
fatalError(io_error, tarName, strerror(errno)); fatalError(io_error, tarName, strerror(errno));
tarDev = tarballStat.st_dev;
tarInode = tarballStat.st_ino;
/* Set the umask for this process so it doesn't /* Set the umask for this process so it doesn't
* screw up permission setting for us later. */ * screw up permission setting for us later. */
@ -757,12 +809,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
/* Read the directory/files and iterate over them one at a time */ /* Read the directory/files and iterate over them one at a time */
while (argc-- > 0) { while (argc-- > 0) {
if (recursiveAction(*argv++, TRUE, FALSE, FALSE, if (recursiveAction(*argv++, TRUE, FALSE, FALSE,
fileAction, fileAction, (void*) &tarFd) == FALSE) { writeFileToTarball, writeFileToTarball,
exit(FALSE); (void*) &tbInfo) == FALSE) {
errorFlag = TRUE;
} }
} }
/* Hang up the tools, close up shop, head home */
close(tarFd); close(tarFd);
if (errorFlag == TRUE) {
errorMsg("tar: Error exit delayed from previous errors\n");
return(FALSE);
}
return( TRUE); return( TRUE);
} }

193
tar.c
View File

@ -1,12 +1,12 @@
/* vi: set sw=4 ts=4: */ /* vi: set sw=4 ts=4: */
/* /*
* Mini tar implementation for busybox
* *
* Mini tar implementation for busybox Note, that as of BusyBox 0.43 tar has * Note, that as of BusyBox 0.43 tar has been completely rewritten from the
* been completely rewritten from the ground up. It still has remnents of the * ground up. It still has remnents of the old code lying about, but it pretty
* old code lying about, but it pretty different (i.e. cleaner, less global * different (i.e. cleaner, less global variables, etc)
* variables, etc)
* *
* Copyright (C) 1999 by Lineo, inc. * Copyright (C) 2000 by Lineo, inc.
* Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
* *
* Based in part in the tar implementation in sash * Based in part in the tar implementation in sash
@ -15,7 +15,7 @@
* provided that this copyright notice remains intact. * provided that this copyright notice remains intact.
* Permission to distribute sash derived code under the GPL has been granted. * Permission to distribute sash derived code under the GPL has been granted.
* *
* Based in part on the tar implementation in busybox-0.28 * Based in part on the tar implementation from busybox-0.28
* Copyright (C) 1995 Bruce Perens * Copyright (C) 1995 Bruce Perens
* This is free software under the GNU General Public License. * This is free software under the GNU General Public License.
* *
@ -162,8 +162,8 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
#ifdef BB_FEATURE_TAR_CREATE #ifdef BB_FEATURE_TAR_CREATE
/* Local procedures to save files into a tar file. */ /* Local procedures to save files into a tar file. */
static int writeTarFile(const char* tarName, int extractFlag, int listFlag, static int writeTarFile(const char* tarName, int tostdoutFlag,
int tostdoutFlag, int verboseFlag, int argc, char **argv); int verboseFlag, int argc, char **argv);
static int putOctal(char *cp, int len, long value); static int putOctal(char *cp, int len, long value);
#endif #endif
@ -249,7 +249,7 @@ extern int tar_main(int argc, char **argv)
#ifndef BB_FEATURE_TAR_CREATE #ifndef BB_FEATURE_TAR_CREATE
fatalError( "This version of tar was not compiled with tar creation support.\n"); fatalError( "This version of tar was not compiled with tar creation support.\n");
#else #else
exit(writeTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag, argc, argv)); exit(writeTarFile(tarName, tostdoutFlag, verboseFlag, argc, argv));
#endif #endif
} else { } else {
exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag)); exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag));
@ -410,8 +410,6 @@ tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag)
mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)); mknod(header->name, header->mode, makedev(header->devmajor, header->devminor));
} else if (S_ISFIFO(header->mode)) { } else if (S_ISFIFO(header->mode)) {
mkfifo(header->name, header->mode); mkfifo(header->name, header->mode);
} else {
open(header->name, O_WRONLY | O_CREAT | O_TRUNC, header->mode);
} }
/* Now set permissions etc for the new directory */ /* Now set permissions etc for the new directory */
@ -625,6 +623,21 @@ endgame:
#ifdef BB_FEATURE_TAR_CREATE #ifdef BB_FEATURE_TAR_CREATE
/* Some info to be carried along when creating a new tarball */
struct TarBallInfo
{
char* fileName; /* File name of the tarball */
int tarFd; /* Open-for-write file descriptor
for the tarball */
struct stat statBuf; /* Stat info for the tarball, letting
us know the inode and device that the
tarball lives, so we can avoid trying
to include the tarball into itself */
int verboseFlag; /* Whether to print extra stuff or not */
};
typedef struct TarBallInfo TarBallInfo;
/* Put an octal string into the specified buffer. /* Put an octal string into the specified buffer.
* The number is zero and space padded and possibly null padded. * The number is zero and space padded and possibly null padded.
* Returns TRUE if successful. */ * Returns TRUE if successful. */
@ -662,41 +675,55 @@ static int putOctal (char *cp, int len, long value)
return TRUE; return TRUE;
} }
/* Write out a tar header for the specified file */ /* Write out a tar header for the specified file/directory/whatever */
static int static int
writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf)
{ {
int i; //int i;
long chksum, sum; //long chksum, sum;
unsigned char *s = (unsigned char *)rawHeader;
struct TarHeader header; if (*fileName=='/') {
static int alreadyWarned=FALSE;
strcpy(header.name, fileName); if (alreadyWarned==FALSE) {
putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777); errorMsg("tar: Removing leading '/' from member names\n");
putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); alreadyWarned=TRUE;
putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
putOctal(header.size, sizeof(header.size), statbuf->st_size);
putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
if (S_ISLNK(statbuf.st_mode)) {
header.type = LNKTYPE;
// Handle SYMTYPE
} else if (S_ISDIR(statbuf.st_mode)) {
header.type = DIRTYPE;
} else if (S_ISCHR(statbuf.st_mode)) {
header.type = CHRTYPE;
} else if (S_ISBLK(statbuf.st_mode)) {
header.type = BLKTYPE;
} else if (S_ISFIFO(statbuf.st_mode)) {
header.type = FIFOTYPE;
} else if (S_ISSOCK(statbuf.st_mode)) {
header.type = S_ISSOCK;
} else if (S_ISLNK(statbuf.st_mode)) {
header.type = LNKTYPE;
} else if (S_ISLNK(statbuf.st_mode)) {
header.type = REGTYPE;
} }
strcpy(header->name, fileName+1);
}
else {
strcpy(header->name, fileName);
}
putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777);
putOctal(header->uid, sizeof(header->uid), statbuf->st_uid);
putOctal(header->gid, sizeof(header->gid), statbuf->st_gid);
putOctal(header->size, sizeof(header->size), statbuf->st_size);
putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime);
if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = LNKTYPE;
// TODO -- Handle SYMTYPE
} else if (S_ISDIR(statbuf->st_mode)) {
header->typeflag = DIRTYPE;
strncat(header->name, "/", sizeof(header->name));
} else if (S_ISCHR(statbuf->st_mode)) {
header->typeflag = CHRTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
} else if (S_ISBLK(statbuf->st_mode)) {
header->typeflag = BLKTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
} else if (S_ISFIFO(statbuf->st_mode)) {
header->typeflag = FIFOTYPE;
} else if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = LNKTYPE;
} else if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = REGTYPE;
} else {
return ( FALSE);
}
return ( TRUE);
#if 0 #if 0
header->linkname = rawHeader->linkname; header->linkname = rawHeader->linkname;
header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
@ -704,31 +731,58 @@ writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
/* Write out the checksum */ /* Write out the checksum */
chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
return ( TRUE);
#endif #endif
return ( TRUE);
} }
static int fileAction(const char *fileName, struct stat *statbuf, void* userData) static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
{ {
int *tarFd=(int*)userData; int inputFileFd;
dprintf(*tarFd, "%s\n", fileName); struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
char header[sizeof(struct TarHeader)];
/* First open the file we want to archive, and make sure all is well */
if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
return( TRUE); return( TRUE);
} }
static int writeTarFile(const char* tarName, int extractFlag, int listFlag, /* It is against the rules to archive a socket */
int tostdoutFlag, int verboseFlag, int argc, char **argv) if (S_ISSOCK(statbuf->st_mode)) {
errorMsg("tar: %s: socket ignored\n", fileName);
return( TRUE);
}
/* It is a bad idea to store the archive we are in the process of creating,
* so check the device and inode to be sure that this particular file isn't
* the new tarball */
if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
tbInfo->statBuf.st_ino == statbuf->st_ino) {
errorMsg("tar: %s: file is the archive; skipping\n", fileName);
return( TRUE);
}
memset( header, 0, sizeof(struct TarHeader));
if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) {
dprintf(tbInfo->tarFd, "%s", header);
}
/* Now do the verbose thing (or not) */
if (tbInfo->verboseFlag==TRUE)
fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name);
return( TRUE);
}
static int writeTarFile(const char* tarName, int tostdoutFlag,
int verboseFlag, int argc, char **argv)
{ {
int tarFd=-1; int tarFd=-1;
//int errorFlag=FALSE; int errorFlag=FALSE;
//TarHeader rawHeader;
//TarInfo header;
//int alreadyWarned=FALSE;
//int skipFileFlag=FALSE; //int skipFileFlag=FALSE;
struct stat tarballStat; struct TarBallInfo tbInfo;
dev_t tarDev = 0; tbInfo.verboseFlag = verboseFlag;
ino_t tarInode = 0;
/* Make sure there is at least one file to tar up. */ /* Make sure there is at least one file to tar up. */
if (argc <= 0) if (argc <= 0)
@ -736,19 +790,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
/* Open the tar file for writing. */ /* Open the tar file for writing. */
if (tostdoutFlag == TRUE) if (tostdoutFlag == TRUE)
tarFd = fileno(stdout); tbInfo.tarFd = fileno(stdout);
else else
tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644); tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (tarFd < 0) { if (tbInfo.tarFd < 0) {
errorMsg( "Error opening '%s': %s\n", tarName, strerror(errno)); errorMsg( "tar: Error opening '%s': %s\n", tarName, strerror(errno));
return ( FALSE); return ( FALSE);
} }
/* Store the device and inode of the tarball, so we can be sure /* Store the stat info for the tarball's file, so
* not to try and include it into itself.... */ * can avoid including the tarball into itself.... */
if (fstat(tarFd, &tarballStat) < 0) if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
fatalError(io_error, tarName, strerror(errno)); fatalError(io_error, tarName, strerror(errno));
tarDev = tarballStat.st_dev;
tarInode = tarballStat.st_ino;
/* Set the umask for this process so it doesn't /* Set the umask for this process so it doesn't
* screw up permission setting for us later. */ * screw up permission setting for us later. */
@ -757,12 +809,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
/* Read the directory/files and iterate over them one at a time */ /* Read the directory/files and iterate over them one at a time */
while (argc-- > 0) { while (argc-- > 0) {
if (recursiveAction(*argv++, TRUE, FALSE, FALSE, if (recursiveAction(*argv++, TRUE, FALSE, FALSE,
fileAction, fileAction, (void*) &tarFd) == FALSE) { writeFileToTarball, writeFileToTarball,
exit(FALSE); (void*) &tbInfo) == FALSE) {
errorFlag = TRUE;
} }
} }
/* Hang up the tools, close up shop, head home */
close(tarFd); close(tarFd);
if (errorFlag == TRUE) {
errorMsg("tar: Error exit delayed from previous errors\n");
return(FALSE);
}
return( TRUE); return( TRUE);
} }