aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-04-04 18:39:50 +0000
committerErik Andersen <andersen@codepoet.org>2000-04-04 18:39:50 +0000
commit68a9ea4208d5661de225fec9be3ffff8b02b8d66 (patch)
treecdda0600efe3f7129e9e17809ae168dda63be66a
parent183da4ade108945f94117a633045cfd6f4ff813a (diff)
downloadbusybox-w32-68a9ea4208d5661de225fec9be3ffff8b02b8d66.tar.gz
busybox-w32-68a9ea4208d5661de225fec9be3ffff8b02b8d66.tar.bz2
busybox-w32-68a9ea4208d5661de225fec9be3ffff8b02b8d66.zip
Update tar so creation of tarballs is much closer to working...
-Erik
-rw-r--r--archival/tar.c195
-rw-r--r--tar.c195
2 files changed, 252 insertions, 138 deletions
diff --git a/archival/tar.c b/archival/tar.c
index af0e4f8ef..f9b3e1813 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -1,12 +1,12 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini tar implementation for busybox
3 * 4 *
4 * Mini tar implementation for busybox Note, that as of BusyBox 0.43 tar has 5 * Note, that as of BusyBox 0.43 tar has been completely rewritten from the
5 * been completely rewritten from the ground up. It still has remnents of the 6 * ground up. It still has remnents of the old code lying about, but it pretty
6 * old code lying about, but it pretty different (i.e. cleaner, less global 7 * different (i.e. cleaner, less global variables, etc)
7 * variables, etc)
8 * 8 *
9 * Copyright (C) 1999 by Lineo, inc. 9 * Copyright (C) 2000 by Lineo, inc.
10 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> 10 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
11 * 11 *
12 * Based in part in the tar implementation in sash 12 * Based in part in the tar implementation in sash
@@ -15,7 +15,7 @@
15 * provided that this copyright notice remains intact. 15 * provided that this copyright notice remains intact.
16 * Permission to distribute sash derived code under the GPL has been granted. 16 * Permission to distribute sash derived code under the GPL has been granted.
17 * 17 *
18 * Based in part on the tar implementation in busybox-0.28 18 * Based in part on the tar implementation from busybox-0.28
19 * Copyright (C) 1995 Bruce Perens 19 * Copyright (C) 1995 Bruce Perens
20 * This is free software under the GNU General Public License. 20 * This is free software under the GNU General Public License.
21 * 21 *
@@ -162,8 +162,8 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
162 162
163#ifdef BB_FEATURE_TAR_CREATE 163#ifdef BB_FEATURE_TAR_CREATE
164/* Local procedures to save files into a tar file. */ 164/* Local procedures to save files into a tar file. */
165static int writeTarFile(const char* tarName, int extractFlag, int listFlag, 165static int writeTarFile(const char* tarName, int tostdoutFlag,
166 int tostdoutFlag, int verboseFlag, int argc, char **argv); 166 int verboseFlag, int argc, char **argv);
167static int putOctal(char *cp, int len, long value); 167static int putOctal(char *cp, int len, long value);
168 168
169#endif 169#endif
@@ -249,7 +249,7 @@ extern int tar_main(int argc, char **argv)
249#ifndef BB_FEATURE_TAR_CREATE 249#ifndef BB_FEATURE_TAR_CREATE
250 fatalError( "This version of tar was not compiled with tar creation support.\n"); 250 fatalError( "This version of tar was not compiled with tar creation support.\n");
251#else 251#else
252 exit(writeTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag, argc, argv)); 252 exit(writeTarFile(tarName, tostdoutFlag, verboseFlag, argc, argv));
253#endif 253#endif
254 } else { 254 } else {
255 exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag)); 255 exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag));
@@ -410,8 +410,6 @@ tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag)
410 mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)); 410 mknod(header->name, header->mode, makedev(header->devmajor, header->devminor));
411 } else if (S_ISFIFO(header->mode)) { 411 } else if (S_ISFIFO(header->mode)) {
412 mkfifo(header->name, header->mode); 412 mkfifo(header->name, header->mode);
413 } else {
414 open(header->name, O_WRONLY | O_CREAT | O_TRUNC, header->mode);
415 } 413 }
416 414
417 /* Now set permissions etc for the new directory */ 415 /* Now set permissions etc for the new directory */
@@ -625,6 +623,21 @@ endgame:
625 623
626#ifdef BB_FEATURE_TAR_CREATE 624#ifdef BB_FEATURE_TAR_CREATE
627 625
626/* Some info to be carried along when creating a new tarball */
627struct TarBallInfo
628{
629 char* fileName; /* File name of the tarball */
630 int tarFd; /* Open-for-write file descriptor
631 for the tarball */
632 struct stat statBuf; /* Stat info for the tarball, letting
633 us know the inode and device that the
634 tarball lives, so we can avoid trying
635 to include the tarball into itself */
636 int verboseFlag; /* Whether to print extra stuff or not */
637};
638typedef struct TarBallInfo TarBallInfo;
639
640
628/* Put an octal string into the specified buffer. 641/* Put an octal string into the specified buffer.
629 * The number is zero and space padded and possibly null padded. 642 * The number is zero and space padded and possibly null padded.
630 * Returns TRUE if successful. */ 643 * Returns TRUE if successful. */
@@ -662,41 +675,55 @@ static int putOctal (char *cp, int len, long value)
662 return TRUE; 675 return TRUE;
663} 676}
664 677
665/* Write out a tar header for the specified file */ 678/* Write out a tar header for the specified file/directory/whatever */
666static int 679static int
667writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) 680writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf)
668{ 681{
669 int i; 682 //int i;
670 long chksum, sum; 683 //long chksum, sum;
671 unsigned char *s = (unsigned char *)rawHeader; 684
672 685 if (*fileName=='/') {
673 struct TarHeader header; 686 static int alreadyWarned=FALSE;
674 687 if (alreadyWarned==FALSE) {
675 strcpy(header.name, fileName); 688 errorMsg("tar: Removing leading '/' from member names\n");
676 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777); 689 alreadyWarned=TRUE;
677 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); 690 }
678 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); 691 strcpy(header->name, fileName+1);
679 putOctal(header.size, sizeof(header.size), statbuf->st_size); 692 }
680 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); 693 else {
681 694 strcpy(header->name, fileName);
682 if (S_ISLNK(statbuf.st_mode)) { 695 }
683 header.type = LNKTYPE; 696 putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777);
684 // Handle SYMTYPE 697 putOctal(header->uid, sizeof(header->uid), statbuf->st_uid);
685 } else if (S_ISDIR(statbuf.st_mode)) { 698 putOctal(header->gid, sizeof(header->gid), statbuf->st_gid);
686 header.type = DIRTYPE; 699 putOctal(header->size, sizeof(header->size), statbuf->st_size);
687 } else if (S_ISCHR(statbuf.st_mode)) { 700 putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime);
688 header.type = CHRTYPE; 701
689 } else if (S_ISBLK(statbuf.st_mode)) { 702 if (S_ISLNK(statbuf->st_mode)) {
690 header.type = BLKTYPE; 703 header->typeflag = LNKTYPE;
691 } else if (S_ISFIFO(statbuf.st_mode)) { 704 // TODO -- Handle SYMTYPE
692 header.type = FIFOTYPE; 705 } else if (S_ISDIR(statbuf->st_mode)) {
693 } else if (S_ISSOCK(statbuf.st_mode)) { 706 header->typeflag = DIRTYPE;
694 header.type = S_ISSOCK; 707 strncat(header->name, "/", sizeof(header->name));
695 } else if (S_ISLNK(statbuf.st_mode)) { 708 } else if (S_ISCHR(statbuf->st_mode)) {
696 header.type = LNKTYPE; 709 header->typeflag = CHRTYPE;
697 } else if (S_ISLNK(statbuf.st_mode)) { 710 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
698 header.type = REGTYPE; 711 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
712 } else if (S_ISBLK(statbuf->st_mode)) {
713 header->typeflag = BLKTYPE;
714 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
715 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
716 } else if (S_ISFIFO(statbuf->st_mode)) {
717 header->typeflag = FIFOTYPE;
718 } else if (S_ISLNK(statbuf->st_mode)) {
719 header->typeflag = LNKTYPE;
720 } else if (S_ISLNK(statbuf->st_mode)) {
721 header->typeflag = REGTYPE;
722 } else {
723 return ( FALSE);
699 } 724 }
725 return ( TRUE);
726
700#if 0 727#if 0
701 header->linkname = rawHeader->linkname; 728 header->linkname = rawHeader->linkname;
702 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); 729 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
@@ -704,31 +731,58 @@ writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
704 731
705 /* Write out the checksum */ 732 /* Write out the checksum */
706 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); 733 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
707#endif
708 734
709 return ( TRUE); 735 return ( TRUE);
736#endif
710} 737}
711 738
712 739
713static int fileAction(const char *fileName, struct stat *statbuf, void* userData) 740static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
714{ 741{
715 int *tarFd=(int*)userData; 742 int inputFileFd;
716 dprintf(*tarFd, "%s\n", fileName); 743 struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
717 return (TRUE); 744 char header[sizeof(struct TarHeader)];
745
746 /* First open the file we want to archive, and make sure all is well */
747 if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
748 errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
749 return( TRUE);
750 }
751
752 /* It is against the rules to archive a socket */
753 if (S_ISSOCK(statbuf->st_mode)) {
754 errorMsg("tar: %s: socket ignored\n", fileName);
755 return( TRUE);
756 }
757
758 /* It is a bad idea to store the archive we are in the process of creating,
759 * so check the device and inode to be sure that this particular file isn't
760 * the new tarball */
761 if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
762 tbInfo->statBuf.st_ino == statbuf->st_ino) {
763 errorMsg("tar: %s: file is the archive; skipping\n", fileName);
764 return( TRUE);
765 }
766
767 memset( header, 0, sizeof(struct TarHeader));
768 if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) {
769 dprintf(tbInfo->tarFd, "%s", header);
770 }
771 /* Now do the verbose thing (or not) */
772 if (tbInfo->verboseFlag==TRUE)
773 fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name);
774
775 return( TRUE);
718} 776}
719 777
720static int writeTarFile(const char* tarName, int extractFlag, int listFlag, 778static int writeTarFile(const char* tarName, int tostdoutFlag,
721 int tostdoutFlag, int verboseFlag, int argc, char **argv) 779 int verboseFlag, int argc, char **argv)
722{ 780{
723 int tarFd=-1; 781 int tarFd=-1;
724 //int errorFlag=FALSE; 782 int errorFlag=FALSE;
725 //TarHeader rawHeader;
726 //TarInfo header;
727 //int alreadyWarned=FALSE;
728 //int skipFileFlag=FALSE; 783 //int skipFileFlag=FALSE;
729 struct stat tarballStat; 784 struct TarBallInfo tbInfo;
730 dev_t tarDev = 0; 785 tbInfo.verboseFlag = verboseFlag;
731 ino_t tarInode = 0;
732 786
733 /* Make sure there is at least one file to tar up. */ 787 /* Make sure there is at least one file to tar up. */
734 if (argc <= 0) 788 if (argc <= 0)
@@ -736,19 +790,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
736 790
737 /* Open the tar file for writing. */ 791 /* Open the tar file for writing. */
738 if (tostdoutFlag == TRUE) 792 if (tostdoutFlag == TRUE)
739 tarFd = fileno(stdout); 793 tbInfo.tarFd = fileno(stdout);
740 else 794 else
741 tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644); 795 tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
742 if (tarFd < 0) { 796 if (tbInfo.tarFd < 0) {
743 errorMsg( "Error opening '%s': %s\n", tarName, strerror(errno)); 797 errorMsg( "tar: Error opening '%s': %s\n", tarName, strerror(errno));
744 return ( FALSE); 798 return ( FALSE);
745 } 799 }
746 /* Store the device and inode of the tarball, so we can be sure 800 /* Store the stat info for the tarball's file, so
747 * not to try and include it into itself.... */ 801 * can avoid including the tarball into itself.... */
748 if (fstat(tarFd, &tarballStat) < 0) 802 if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
749 fatalError(io_error, tarName, strerror(errno)); 803 fatalError(io_error, tarName, strerror(errno));
750 tarDev = tarballStat.st_dev;
751 tarInode = tarballStat.st_ino;
752 804
753 /* Set the umask for this process so it doesn't 805 /* Set the umask for this process so it doesn't
754 * screw up permission setting for us later. */ 806 * screw up permission setting for us later. */
@@ -757,12 +809,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
757 /* Read the directory/files and iterate over them one at a time */ 809 /* Read the directory/files and iterate over them one at a time */
758 while (argc-- > 0) { 810 while (argc-- > 0) {
759 if (recursiveAction(*argv++, TRUE, FALSE, FALSE, 811 if (recursiveAction(*argv++, TRUE, FALSE, FALSE,
760 fileAction, fileAction, (void*) &tarFd) == FALSE) { 812 writeFileToTarball, writeFileToTarball,
761 exit(FALSE); 813 (void*) &tbInfo) == FALSE) {
814 errorFlag = TRUE;
762 } 815 }
763 } 816 }
764 817 /* Hang up the tools, close up shop, head home */
765 close(tarFd); 818 close(tarFd);
819 if (errorFlag == TRUE) {
820 errorMsg("tar: Error exit delayed from previous errors\n");
821 return(FALSE);
822 }
766 return( TRUE); 823 return( TRUE);
767} 824}
768 825
diff --git a/tar.c b/tar.c
index af0e4f8ef..f9b3e1813 100644
--- a/tar.c
+++ b/tar.c
@@ -1,12 +1,12 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini tar implementation for busybox
3 * 4 *
4 * Mini tar implementation for busybox Note, that as of BusyBox 0.43 tar has 5 * Note, that as of BusyBox 0.43 tar has been completely rewritten from the
5 * been completely rewritten from the ground up. It still has remnents of the 6 * ground up. It still has remnents of the old code lying about, but it pretty
6 * old code lying about, but it pretty different (i.e. cleaner, less global 7 * different (i.e. cleaner, less global variables, etc)
7 * variables, etc)
8 * 8 *
9 * Copyright (C) 1999 by Lineo, inc. 9 * Copyright (C) 2000 by Lineo, inc.
10 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> 10 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
11 * 11 *
12 * Based in part in the tar implementation in sash 12 * Based in part in the tar implementation in sash
@@ -15,7 +15,7 @@
15 * provided that this copyright notice remains intact. 15 * provided that this copyright notice remains intact.
16 * Permission to distribute sash derived code under the GPL has been granted. 16 * Permission to distribute sash derived code under the GPL has been granted.
17 * 17 *
18 * Based in part on the tar implementation in busybox-0.28 18 * Based in part on the tar implementation from busybox-0.28
19 * Copyright (C) 1995 Bruce Perens 19 * Copyright (C) 1995 Bruce Perens
20 * This is free software under the GNU General Public License. 20 * This is free software under the GNU General Public License.
21 * 21 *
@@ -162,8 +162,8 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
162 162
163#ifdef BB_FEATURE_TAR_CREATE 163#ifdef BB_FEATURE_TAR_CREATE
164/* Local procedures to save files into a tar file. */ 164/* Local procedures to save files into a tar file. */
165static int writeTarFile(const char* tarName, int extractFlag, int listFlag, 165static int writeTarFile(const char* tarName, int tostdoutFlag,
166 int tostdoutFlag, int verboseFlag, int argc, char **argv); 166 int verboseFlag, int argc, char **argv);
167static int putOctal(char *cp, int len, long value); 167static int putOctal(char *cp, int len, long value);
168 168
169#endif 169#endif
@@ -249,7 +249,7 @@ extern int tar_main(int argc, char **argv)
249#ifndef BB_FEATURE_TAR_CREATE 249#ifndef BB_FEATURE_TAR_CREATE
250 fatalError( "This version of tar was not compiled with tar creation support.\n"); 250 fatalError( "This version of tar was not compiled with tar creation support.\n");
251#else 251#else
252 exit(writeTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag, argc, argv)); 252 exit(writeTarFile(tarName, tostdoutFlag, verboseFlag, argc, argv));
253#endif 253#endif
254 } else { 254 } else {
255 exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag)); 255 exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag));
@@ -410,8 +410,6 @@ tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag)
410 mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)); 410 mknod(header->name, header->mode, makedev(header->devmajor, header->devminor));
411 } else if (S_ISFIFO(header->mode)) { 411 } else if (S_ISFIFO(header->mode)) {
412 mkfifo(header->name, header->mode); 412 mkfifo(header->name, header->mode);
413 } else {
414 open(header->name, O_WRONLY | O_CREAT | O_TRUNC, header->mode);
415 } 413 }
416 414
417 /* Now set permissions etc for the new directory */ 415 /* Now set permissions etc for the new directory */
@@ -625,6 +623,21 @@ endgame:
625 623
626#ifdef BB_FEATURE_TAR_CREATE 624#ifdef BB_FEATURE_TAR_CREATE
627 625
626/* Some info to be carried along when creating a new tarball */
627struct TarBallInfo
628{
629 char* fileName; /* File name of the tarball */
630 int tarFd; /* Open-for-write file descriptor
631 for the tarball */
632 struct stat statBuf; /* Stat info for the tarball, letting
633 us know the inode and device that the
634 tarball lives, so we can avoid trying
635 to include the tarball into itself */
636 int verboseFlag; /* Whether to print extra stuff or not */
637};
638typedef struct TarBallInfo TarBallInfo;
639
640
628/* Put an octal string into the specified buffer. 641/* Put an octal string into the specified buffer.
629 * The number is zero and space padded and possibly null padded. 642 * The number is zero and space padded and possibly null padded.
630 * Returns TRUE if successful. */ 643 * Returns TRUE if successful. */
@@ -662,41 +675,55 @@ static int putOctal (char *cp, int len, long value)
662 return TRUE; 675 return TRUE;
663} 676}
664 677
665/* Write out a tar header for the specified file */ 678/* Write out a tar header for the specified file/directory/whatever */
666static int 679static int
667writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) 680writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf)
668{ 681{
669 int i; 682 //int i;
670 long chksum, sum; 683 //long chksum, sum;
671 unsigned char *s = (unsigned char *)rawHeader; 684
672 685 if (*fileName=='/') {
673 struct TarHeader header; 686 static int alreadyWarned=FALSE;
674 687 if (alreadyWarned==FALSE) {
675 strcpy(header.name, fileName); 688 errorMsg("tar: Removing leading '/' from member names\n");
676 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777); 689 alreadyWarned=TRUE;
677 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); 690 }
678 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); 691 strcpy(header->name, fileName+1);
679 putOctal(header.size, sizeof(header.size), statbuf->st_size); 692 }
680 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); 693 else {
681 694 strcpy(header->name, fileName);
682 if (S_ISLNK(statbuf.st_mode)) { 695 }
683 header.type = LNKTYPE; 696 putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777);
684 // Handle SYMTYPE 697 putOctal(header->uid, sizeof(header->uid), statbuf->st_uid);
685 } else if (S_ISDIR(statbuf.st_mode)) { 698 putOctal(header->gid, sizeof(header->gid), statbuf->st_gid);
686 header.type = DIRTYPE; 699 putOctal(header->size, sizeof(header->size), statbuf->st_size);
687 } else if (S_ISCHR(statbuf.st_mode)) { 700 putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime);
688 header.type = CHRTYPE; 701
689 } else if (S_ISBLK(statbuf.st_mode)) { 702 if (S_ISLNK(statbuf->st_mode)) {
690 header.type = BLKTYPE; 703 header->typeflag = LNKTYPE;
691 } else if (S_ISFIFO(statbuf.st_mode)) { 704 // TODO -- Handle SYMTYPE
692 header.type = FIFOTYPE; 705 } else if (S_ISDIR(statbuf->st_mode)) {
693 } else if (S_ISSOCK(statbuf.st_mode)) { 706 header->typeflag = DIRTYPE;
694 header.type = S_ISSOCK; 707 strncat(header->name, "/", sizeof(header->name));
695 } else if (S_ISLNK(statbuf.st_mode)) { 708 } else if (S_ISCHR(statbuf->st_mode)) {
696 header.type = LNKTYPE; 709 header->typeflag = CHRTYPE;
697 } else if (S_ISLNK(statbuf.st_mode)) { 710 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
698 header.type = REGTYPE; 711 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
712 } else if (S_ISBLK(statbuf->st_mode)) {
713 header->typeflag = BLKTYPE;
714 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
715 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
716 } else if (S_ISFIFO(statbuf->st_mode)) {
717 header->typeflag = FIFOTYPE;
718 } else if (S_ISLNK(statbuf->st_mode)) {
719 header->typeflag = LNKTYPE;
720 } else if (S_ISLNK(statbuf->st_mode)) {
721 header->typeflag = REGTYPE;
722 } else {
723 return ( FALSE);
699 } 724 }
725 return ( TRUE);
726
700#if 0 727#if 0
701 header->linkname = rawHeader->linkname; 728 header->linkname = rawHeader->linkname;
702 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); 729 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
@@ -704,31 +731,58 @@ writeTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
704 731
705 /* Write out the checksum */ 732 /* Write out the checksum */
706 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); 733 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
707#endif
708 734
709 return ( TRUE); 735 return ( TRUE);
736#endif
710} 737}
711 738
712 739
713static int fileAction(const char *fileName, struct stat *statbuf, void* userData) 740static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
714{ 741{
715 int *tarFd=(int*)userData; 742 int inputFileFd;
716 dprintf(*tarFd, "%s\n", fileName); 743 struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
717 return (TRUE); 744 char header[sizeof(struct TarHeader)];
745
746 /* First open the file we want to archive, and make sure all is well */
747 if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
748 errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
749 return( TRUE);
750 }
751
752 /* It is against the rules to archive a socket */
753 if (S_ISSOCK(statbuf->st_mode)) {
754 errorMsg("tar: %s: socket ignored\n", fileName);
755 return( TRUE);
756 }
757
758 /* It is a bad idea to store the archive we are in the process of creating,
759 * so check the device and inode to be sure that this particular file isn't
760 * the new tarball */
761 if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
762 tbInfo->statBuf.st_ino == statbuf->st_ino) {
763 errorMsg("tar: %s: file is the archive; skipping\n", fileName);
764 return( TRUE);
765 }
766
767 memset( header, 0, sizeof(struct TarHeader));
768 if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) {
769 dprintf(tbInfo->tarFd, "%s", header);
770 }
771 /* Now do the verbose thing (or not) */
772 if (tbInfo->verboseFlag==TRUE)
773 fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name);
774
775 return( TRUE);
718} 776}
719 777
720static int writeTarFile(const char* tarName, int extractFlag, int listFlag, 778static int writeTarFile(const char* tarName, int tostdoutFlag,
721 int tostdoutFlag, int verboseFlag, int argc, char **argv) 779 int verboseFlag, int argc, char **argv)
722{ 780{
723 int tarFd=-1; 781 int tarFd=-1;
724 //int errorFlag=FALSE; 782 int errorFlag=FALSE;
725 //TarHeader rawHeader;
726 //TarInfo header;
727 //int alreadyWarned=FALSE;
728 //int skipFileFlag=FALSE; 783 //int skipFileFlag=FALSE;
729 struct stat tarballStat; 784 struct TarBallInfo tbInfo;
730 dev_t tarDev = 0; 785 tbInfo.verboseFlag = verboseFlag;
731 ino_t tarInode = 0;
732 786
733 /* Make sure there is at least one file to tar up. */ 787 /* Make sure there is at least one file to tar up. */
734 if (argc <= 0) 788 if (argc <= 0)
@@ -736,19 +790,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
736 790
737 /* Open the tar file for writing. */ 791 /* Open the tar file for writing. */
738 if (tostdoutFlag == TRUE) 792 if (tostdoutFlag == TRUE)
739 tarFd = fileno(stdout); 793 tbInfo.tarFd = fileno(stdout);
740 else 794 else
741 tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644); 795 tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
742 if (tarFd < 0) { 796 if (tbInfo.tarFd < 0) {
743 errorMsg( "Error opening '%s': %s\n", tarName, strerror(errno)); 797 errorMsg( "tar: Error opening '%s': %s\n", tarName, strerror(errno));
744 return ( FALSE); 798 return ( FALSE);
745 } 799 }
746 /* Store the device and inode of the tarball, so we can be sure 800 /* Store the stat info for the tarball's file, so
747 * not to try and include it into itself.... */ 801 * can avoid including the tarball into itself.... */
748 if (fstat(tarFd, &tarballStat) < 0) 802 if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
749 fatalError(io_error, tarName, strerror(errno)); 803 fatalError(io_error, tarName, strerror(errno));
750 tarDev = tarballStat.st_dev;
751 tarInode = tarballStat.st_ino;
752 804
753 /* Set the umask for this process so it doesn't 805 /* Set the umask for this process so it doesn't
754 * screw up permission setting for us later. */ 806 * screw up permission setting for us later. */
@@ -757,12 +809,17 @@ static int writeTarFile(const char* tarName, int extractFlag, int listFlag,
757 /* Read the directory/files and iterate over them one at a time */ 809 /* Read the directory/files and iterate over them one at a time */
758 while (argc-- > 0) { 810 while (argc-- > 0) {
759 if (recursiveAction(*argv++, TRUE, FALSE, FALSE, 811 if (recursiveAction(*argv++, TRUE, FALSE, FALSE,
760 fileAction, fileAction, (void*) &tarFd) == FALSE) { 812 writeFileToTarball, writeFileToTarball,
761 exit(FALSE); 813 (void*) &tbInfo) == FALSE) {
814 errorFlag = TRUE;
762 } 815 }
763 } 816 }
764 817 /* Hang up the tools, close up shop, head home */
765 close(tarFd); 818 close(tarFd);
819 if (errorFlag == TRUE) {
820 errorMsg("tar: Error exit delayed from previous errors\n");
821 return(FALSE);
822 }
766 return( TRUE); 823 return( TRUE);
767} 824}
768 825