- int status, tarFd=-1;
- int errorFlag=FALSE;
- TarHeader rawHeader;
- TarInfo header;
- char** tmpList;
-
- /* Open the tar file for reading. */
- if (!strcmp(tarName, "-"))
- tarFd = fileno(stdin);
- else
- tarFd = open(tarName, O_RDONLY);
- if (tarFd < 0) {
- errorMsg( "Error opening '%s': %s\n", tarName, strerror(errno));
- return ( FALSE);
- }
-
- /* Set the umask for this process so it doesn't
- * screw up permission setting for us later. */
- umask(0);
-
- /* Read the tar file, and iterate over it one file at a time */
- while ( (status = fullRead(tarFd, (char*)&rawHeader, TAR_BLOCK_SIZE)) == TAR_BLOCK_SIZE ) {
-
- /* First, try to read the header */
- if ( readTarHeader(&rawHeader, &header) == FALSE ) {
- if ( *(header.name) == '\0' ) {
- goto endgame;
- } else {
- errorFlag=TRUE;
- errorMsg("Bad tar header, skipping\n");
- continue;
- }
- }
- if ( *(header.name) == '\0' )
- 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
- if (*extractList != NULL) {
- int skipFlag = TRUE;
- for (tmpList = extractList; *tmpList != NULL; tmpList++) {
- 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 */
- skipFlag = FALSE;
- break;
- }
- }
- /* There are not the droids you're looking for, move along */
- if (skipFlag == TRUE) {
- if ( header.type==REGTYPE || header.type==REGTYPE0 )
- tarExtractRegularFile(&header, FALSE, FALSE);
- continue;
- }
- }
-
- if (listFlag == TRUE) {
- /* Special treatment if the list (-t) flag is on */
- if (verboseFlag == TRUE) {
- int len, len1;
- char buf[35];
- struct tm *tm = localtime (&(header.mtime));
-
- len=printf("%s ", modeString(header.mode));
- memset(buf, 0, 8*sizeof(char));
- my_getpwuid(buf, header.uid);
- if (! *buf)
- len+=printf("%d", header.uid);
- else
- len+=printf("%s", buf);
- memset(buf, 0, 8*sizeof(char));
- my_getgrgid(buf, header.gid);
- if (! *buf)
- len+=printf("/%-d ", header.gid);
- else
- len+=printf("/%-s ", buf);
-
- if (header.type==CHRTYPE || header.type==BLKTYPE) {
- len1=snprintf(buf, sizeof(buf), "%ld,%-ld ",
- header.devmajor, header.devminor);
- } else {
- len1=snprintf(buf, sizeof(buf), "%lu ", (long)header.size);
- }
- /* Jump through some hoops to make the columns match up */
- for(;(len+len1)<31;len++)
- printf(" ");
- printf(buf);
-
- /* Use ISO 8610 time format */
- if (tm) {
- printf ("%04d-%02d-%02d %02d:%02d:%02d ",
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- }
- }
- printf("%s", header.name);
- if (verboseFlag == TRUE) {
- if (header.type==LNKTYPE) /* If this is a link, say so */
- printf(" link to %s", header.linkname);
- else if (header.type==SYMTYPE)
- printf(" -> %s", header.linkname);
- }
- printf("\n");
- }
-
- /* List contents if we are supposed to do that */
- if (verboseFlag == TRUE && extractFlag == TRUE) {
- /* Now the normal listing */
- FILE *vbFd = stdout;
- if (tostdoutFlag == TRUE) // If the archive goes to stdout, verbose to stderr
- vbFd = stderr;
- fprintf(vbFd, "%s\n", header.name);
- }
-
- /* Remove files if we would overwrite them */
- if (extractFlag == TRUE && tostdoutFlag == FALSE)
- unlink(header.name);
-
- /* If we got here, we can be certain we have a legitimate
- * header to work with. So work with it. */
- switch ( header.type ) {
- case REGTYPE:
- case REGTYPE0:
- /* If the name ends in a '/' then assume it is
- * supposed to be a directory, and fall through */
- if (header.name[strlen(header.name)-1] != '/') {
- if (tarExtractRegularFile(&header, extractFlag, tostdoutFlag)==FALSE)
- errorFlag=TRUE;
- break;
- }
- case DIRTYPE:
- if (tarExtractDirectory( &header, extractFlag, tostdoutFlag)==FALSE)
- errorFlag=TRUE;
- break;
- case LNKTYPE:
- if (tarExtractHardLink( &header, extractFlag, tostdoutFlag)==FALSE)
- errorFlag=TRUE;
- break;
- case SYMTYPE:
- if (tarExtractSymLink( &header, extractFlag, tostdoutFlag)==FALSE)
- errorFlag=TRUE;
- break;
- case CHRTYPE:
- case BLKTYPE:
- case FIFOTYPE:
- if (tarExtractSpecial( &header, extractFlag, tostdoutFlag)==FALSE)
- errorFlag=TRUE;
- break;
- default:
- close( tarFd);
- return( FALSE);
- }
- }
- close(tarFd);
- if (status > 0) {
- /* Bummer - we read a partial header */
- errorMsg( "Error reading '%s': %s\n", tarName, strerror(errno));
- return ( FALSE);