aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-04-05 01:00:52 +0000
committerErik Andersen <andersen@codepoet.org>2000-04-05 01:00:52 +0000
commit5661fe078eed752780b11f3f4fdd33bbd76a6c5e (patch)
tree901159af2b1e62084f258d893949fd9b2fd2d689
parentcbb0a4b40d32a653957d2c9ecb6fe1a70b30d907 (diff)
downloadbusybox-w32-5661fe078eed752780b11f3f4fdd33bbd76a6c5e.tar.gz
busybox-w32-5661fe078eed752780b11f3f4fdd33bbd76a6c5e.tar.bz2
busybox-w32-5661fe078eed752780b11f3f4fdd33bbd76a6c5e.zip
Tar now works perfectly. It behaves much better now then it
used to. Only thing left to do is add in exclude (-X) option. -Erik
-rw-r--r--TODO53
-rw-r--r--applets/busybox.c4
-rw-r--r--archival/tar.c179
-rw-r--r--busybox.c4
-rw-r--r--kill.c2
-rw-r--r--procps/kill.c2
-rw-r--r--tar.c179
-rw-r--r--utility.c4
8 files changed, 247 insertions, 180 deletions
diff --git a/TODO b/TODO
index 87f48db38..421c402e3 100644
--- a/TODO
+++ b/TODO
@@ -15,15 +15,12 @@ around to it some time. If you have any good ideas, please let me know.
15 15
16----------- 16-----------
17 17
18* Allow tar to create archives with sockets, devices, and other special files
19* Make insmod actually work 18* Make insmod actually work
20* dnsdomainname 19* dnsdomainname
21* traceroute/netstat 20* traceroute/netstat
22* rdate 21* rdate
23* hwclock 22* hwclock
24* killall
25* stty 23* stty
26* tr
27* cut 24* cut
28* expr (maybe?) (ash builtin?) 25* expr (maybe?) (ash builtin?)
29 26
@@ -40,58 +37,17 @@ and then start with the biggest things and make them smaller...
40 37
41busybox.defs.h is too big and hard to follow. 38busybox.defs.h is too big and hard to follow.
42 39
43I either need to add a better build system (like the Linux kernel?) 40Perhaps I need to add a better build system (like the Linux kernel?)
44or I need to split up busybox.defs.h into coherent chunks (i.e.
45busybox.defs.h just has a bunch of:
46
47#include "fileutils.h"
48#include "shellutils.h"
49
50which would then have smaller sets of #defines...
51Hmm. Needs to be carefully thought out.
52 41
53----------------------- 42-----------------------
54 43
55 44
56-rw-r--r-- 1000/1000 4398 2000-01-06 21:55 uniq.c
57-rw-r--r-- 1000/1000 1568 1999-10-20 18:08 update.c
58-rw-r----- 0/1000 1168 2000-01-29 21:03 update.o
59-rw-r--r-- 1000/1000 22820 2000-01-05 11:36 utility.c
60-rw-r----- 0/1000 7372 2000-01-29 21:03 utility.o
61tar: Skipping to next file header
62tar: Skipping to next file header
63tar: Archive - EOF not on block boundary
64tar: Error is not recoverable: exiting now
65
66
67#1 You are storing by id instead of name like normal tar. Did you realize this?
68(or am I missing some compile option? )ctar did not do this, and I don't think
69it's a good idea for LRP.
70
71#2
72ctar did not produce the EOF error like your tar does. I believe you need to
73pad the end of the archive with at least 2 tarsized (512byte) blocks. (I
74think???)
75
76#3
77There is no exclude file(s) option to tar. LRP's packaging system can not 45There is no exclude file(s) option to tar. LRP's packaging system can not
78function without this. Will you have the time to add this soon? 46function without this. Will you have the time to add this soon?
79 47
80 48
81----------------------- 49-----------------------
82 50
83cd /mnt
84mkdir BACKUP
85mv * BACKUP
86
87Today, "mv" behaved as a cp -a and my disk becomed full. It does not
88work properly either when renaming a directory into something else
89(it produces a lot of disk activity when doing this).
90
91
92-----------------------
93
94
95Feature request: 51Feature request:
96 52
97/bin/busybox --install -s which makes all links to commands that it 53/bin/busybox --install -s which makes all links to commands that it
@@ -114,13 +70,6 @@ I'll add this to the TODO list,
114----------------------- 70-----------------------
115 71
116 72
117 In utility.c:copyFile: It uses followLinks for both source and
118 destination files... is that right for `mv'? Will need to revisit
119 the GNU, freeBSD, and MINIX versions for this... Should read the
120 Unix98 and POSIX specs also.
121
122-----------------------
123
124 I think that the add_inode &c in utility.c needs to also stow the 73 I think that the add_inode &c in utility.c needs to also stow the
125 st_dev field, and that du.c should NOT call `reset_inode_list' 74 st_dev field, and that du.c should NOT call `reset_inode_list'
126 because there can be hard links from inside one argv/ to inside 75 because there can be hard links from inside one argv/ to inside
diff --git a/applets/busybox.c b/applets/busybox.c
index c2477a537..9a48f4961 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -382,8 +382,8 @@ int busybox_main(int argc, char **argv)
382 fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); 382 fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
383 fprintf(stderr, " or: [function] [arguments]...\n\n"); 383 fprintf(stderr, " or: [function] [arguments]...\n\n");
384 fprintf(stderr, 384 fprintf(stderr,
385 "\tMost people will create a link to busybox for each\n" 385 "\tMost people will create a link to busybox for each function\n"
386 "\tfunction name, and busybox will act like whatever you invoke it as.\n"); 386 "\tname, and busybox will act like whatever you invoke it as.\n");
387 fprintf(stderr, "\nCurrently defined functions:\n"); 387 fprintf(stderr, "\nCurrently defined functions:\n");
388 388
389 while (a->name != 0) { 389 while (a->name != 0) {
diff --git a/archival/tar.c b/archival/tar.c
index f9b3e1813..979821ec0 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -56,7 +56,8 @@
56 56
57static const char tar_usage[] = 57static const char tar_usage[] =
58 "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" 58 "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n"
59 "Create, extract, or list files from a tar file.\n\n" 59 "Create, extract, or list files from a tar file. Note that\n"
60 "this version of tar packs hard links as separate files.\n\n"
60 "Options:\n" 61 "Options:\n"
61 62
62 "\tc=create, x=extract, t=list contents, v=verbose,\n" 63 "\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -110,10 +111,10 @@ typedef struct TarHeader TarHeader;
110 111
111/* A few useful constants */ 112/* A few useful constants */
112#define TAR_MAGIC "ustar" /* ustar and a null */ 113#define TAR_MAGIC "ustar" /* ustar and a null */
113#define TAR_VERSION "00" /* 00 and no null */ 114//#define TAR_VERSION "00" /* 00 and no null */
115#define TAR_VERSION " " /* Be compatable with old GNU format */
114#define TAR_MAGIC_LEN 6 116#define TAR_MAGIC_LEN 6
115#define TAR_VERSION_LEN 2 117#define TAR_VERSION_LEN 2
116#define TAR_NAME_LEN 100
117#define TAR_BLOCK_SIZE 512 118#define TAR_BLOCK_SIZE 512
118 119
119/* A nice enum with all the possible tar file content types */ 120/* A nice enum with all the possible tar file content types */
@@ -366,7 +367,8 @@ tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag)
366 return; 367 return;
367 368
368 if (link(header->linkname, header->name) < 0) { 369 if (link(header->linkname, header->name) < 0) {
369 errorMsg("Error creating hard link '%s': %s\n", header->linkname, strerror(errno)); 370 errorMsg("Error creating hard link '%s' to '%s': %s\n",
371 header->name, header->linkname, strerror(errno));
370 return; 372 return;
371 } 373 }
372 374
@@ -382,7 +384,8 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag)
382 384
383#ifdef S_ISLNK 385#ifdef S_ISLNK
384 if (symlink(header->linkname, header->name) < 0) { 386 if (symlink(header->linkname, header->name) < 0) {
385 errorMsg("Error creating symlink '%s': %s\n", header->linkname, strerror(errno)); 387 errorMsg("Error creating symlink '%s' to '%s': %s\n",
388 header->name, header->linkname, strerror(errno));
386 return; 389 return;
387 } 390 }
388 /* Try to change ownership of the symlink. 391 /* Try to change ownership of the symlink.
@@ -644,18 +647,15 @@ typedef struct TarBallInfo TarBallInfo;
644static int putOctal (char *cp, int len, long value) 647static int putOctal (char *cp, int len, long value)
645{ 648{
646 int tempLength; 649 int tempLength;
647 char *tempString;
648 char tempBuffer[32]; 650 char tempBuffer[32];
651 char *tempString = tempBuffer;
649 652
650 /* Create a string of the specified length with an initial space, 653 /* Create a string of the specified length with an initial space,
651 * leading zeroes and the octal number, and a trailing null. */ 654 * leading zeroes and the octal number, and a trailing null. */
652 tempString = tempBuffer; 655 sprintf (tempString, "%0*lo", len - 1, value);
653
654 sprintf (tempString, " %0*lo", len - 2, value);
655
656 tempLength = strlen (tempString) + 1;
657 656
658 /* If the string is too large, suppress the leading space. */ 657 /* If the string is too large, suppress the leading space. */
658 tempLength = strlen (tempString) + 1;
659 if (tempLength > len) { 659 if (tempLength > len) {
660 tempLength--; 660 tempLength--;
661 tempString++; 661 tempString++;
@@ -677,10 +677,14 @@ static int putOctal (char *cp, int len, long value)
677 677
678/* Write out a tar header for the specified file/directory/whatever */ 678/* Write out a tar header for the specified file/directory/whatever */
679static int 679static int
680writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf) 680writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *statbuf)
681{ 681{
682 //int i; 682 long chksum=0;
683 //long chksum, sum; 683 struct TarHeader header;
684 const unsigned char *cp = (const unsigned char *) &header;
685 ssize_t size = sizeof(struct TarHeader);
686
687 memset( &header, 0, size);
684 688
685 if (*fileName=='/') { 689 if (*fileName=='/') {
686 static int alreadyWarned=FALSE; 690 static int alreadyWarned=FALSE;
@@ -688,66 +692,88 @@ writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *stat
688 errorMsg("tar: Removing leading '/' from member names\n"); 692 errorMsg("tar: Removing leading '/' from member names\n");
689 alreadyWarned=TRUE; 693 alreadyWarned=TRUE;
690 } 694 }
691 strcpy(header->name, fileName+1); 695 strcpy(header.name, fileName+1);
692 } 696 }
693 else { 697 else {
694 strcpy(header->name, fileName); 698 strcpy(header.name, fileName);
695 } 699 }
696 putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777); 700 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
697 putOctal(header->uid, sizeof(header->uid), statbuf->st_uid); 701 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
698 putOctal(header->gid, sizeof(header->gid), statbuf->st_gid); 702 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
699 putOctal(header->size, sizeof(header->size), statbuf->st_size); 703 putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */
700 putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime); 704 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
701 705 strncpy(header.magic, TAR_MAGIC TAR_VERSION,
706 TAR_MAGIC_LEN + TAR_VERSION_LEN );
707
708 my_getpwuid(header.uname, statbuf->st_uid);
709 /* Put some sort of sane fallback in place... */
710 if (! *header.uname)
711 strncpy(header.uname, "root", 5);
712 my_getgrgid(header.gname, statbuf->st_gid);
713 if (! *header.uname)
714 strncpy(header.uname, "root", 5);
715
716 // FIXME: (or most likely not) I break Hard Links
702 if (S_ISLNK(statbuf->st_mode)) { 717 if (S_ISLNK(statbuf->st_mode)) {
703 header->typeflag = LNKTYPE; 718 char buffer[BUFSIZ];
704 // TODO -- Handle SYMTYPE 719 header.typeflag = SYMTYPE;
720 if ( readlink(fileName, buffer, sizeof(buffer) - 1) < 0) {
721 errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
722 return ( FALSE);
723 }
724 strncpy(header.linkname, buffer, sizeof(header.linkname));
705 } else if (S_ISDIR(statbuf->st_mode)) { 725 } else if (S_ISDIR(statbuf->st_mode)) {
706 header->typeflag = DIRTYPE; 726 header.typeflag = DIRTYPE;
707 strncat(header->name, "/", sizeof(header->name)); 727 strncat(header.name, "/", sizeof(header.name));
708 } else if (S_ISCHR(statbuf->st_mode)) { 728 } else if (S_ISCHR(statbuf->st_mode)) {
709 header->typeflag = CHRTYPE; 729 header.typeflag = CHRTYPE;
710 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); 730 putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
711 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); 731 putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
712 } else if (S_ISBLK(statbuf->st_mode)) { 732 } else if (S_ISBLK(statbuf->st_mode)) {
713 header->typeflag = BLKTYPE; 733 header.typeflag = BLKTYPE;
714 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); 734 putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
715 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); 735 putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
716 } else if (S_ISFIFO(statbuf->st_mode)) { 736 } else if (S_ISFIFO(statbuf->st_mode)) {
717 header->typeflag = FIFOTYPE; 737 header.typeflag = FIFOTYPE;
718 } else if (S_ISLNK(statbuf->st_mode)) { 738 } else if (S_ISREG(statbuf->st_mode)) {
719 header->typeflag = LNKTYPE; 739 header.typeflag = REGTYPE;
720 } else if (S_ISLNK(statbuf->st_mode)) { 740 putOctal(header.size, sizeof(header.size), statbuf->st_size);
721 header->typeflag = REGTYPE;
722 } else { 741 } else {
742 errorMsg("tar: %s: Unknown file type\n", fileName);
723 return ( FALSE); 743 return ( FALSE);
724 } 744 }
725 return ( TRUE);
726
727#if 0
728 header->linkname = rawHeader->linkname;
729 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
730 header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
731 745
732 /* Write out the checksum */ 746 /* Calculate and store the checksum (i.e. the sum of all of the bytes of
733 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); 747 * the header). The checksum field must be filled with blanks for the
748 * calculation. The checksum field is formatted differently from the
749 * other fields: it has [6] digits, a null, then a space -- rather than
750 * digits, followed by a null like the other fields... */
751 memset(header.chksum, ' ', sizeof(header.chksum));
752 cp = (const unsigned char *) &header;
753 while (size-- > 0)
754 chksum += *cp++;
755 putOctal(header.chksum, 7, chksum);
756
757 /* Now write the header out to disk */
758 if ((size=fullWrite(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) {
759 errorMsg(io_error, fileName, strerror(errno));
760 return ( FALSE);
761 }
762 /* Pad the header up to the tar block size */
763 for (; size<TAR_BLOCK_SIZE; size++) {
764 write(tbInfo->tarFd, "\0", 1);
765 }
766 /* Now do the verbose thing (or not) */
767 if (tbInfo->verboseFlag==TRUE)
768 fprintf(stdout, "%s\n", header.name);
734 769
735 return ( TRUE); 770 return ( TRUE);
736#endif
737} 771}
738 772
739 773
740static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) 774static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
741{ 775{
742 int inputFileFd;
743 struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; 776 struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
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 777
752 /* It is against the rules to archive a socket */ 778 /* It is against the rules to archive a socket */
753 if (S_ISSOCK(statbuf->st_mode)) { 779 if (S_ISSOCK(statbuf->st_mode)) {
@@ -764,13 +790,41 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void*
764 return( TRUE); 790 return( TRUE);
765 } 791 }
766 792
767 memset( header, 0, sizeof(struct TarHeader)); 793 if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) {
768 if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) { 794 return( FALSE);
769 dprintf(tbInfo->tarFd, "%s", header);
770 } 795 }
771 /* Now do the verbose thing (or not) */ 796
772 if (tbInfo->verboseFlag==TRUE) 797 /* Now, if the file is a regular file, copy it out to the tarball */
773 fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name); 798 if (S_ISREG(statbuf->st_mode)) {
799 int inputFileFd;
800 char buffer[BUFSIZ];
801 ssize_t size=0, readSize=0;
802
803 /* open the file we want to archive, and make sure all is well */
804 if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
805 errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
806 return( FALSE);
807 }
808
809 /* write the file to the archive */
810 while ( (size = fullRead(inputFileFd, buffer, sizeof(buffer))) > 0 ) {
811 if (fullWrite(tbInfo->tarFd, buffer, size) != size ) {
812 /* Output file seems to have a problem */
813 errorMsg(io_error, fileName, strerror(errno));
814 return( FALSE);
815 }
816 readSize+=size;
817 }
818 if (size == -1) {
819 errorMsg(io_error, fileName, strerror(errno));
820 return( FALSE);
821 }
822 /* Pad the file up to the tar block size */
823 for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) {
824 write(tbInfo->tarFd, "\0", 1);
825 }
826 close( inputFileFd);
827 }
774 828
775 return( TRUE); 829 return( TRUE);
776} 830}
@@ -780,6 +834,7 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
780{ 834{
781 int tarFd=-1; 835 int tarFd=-1;
782 int errorFlag=FALSE; 836 int errorFlag=FALSE;
837 ssize_t size;
783 //int skipFileFlag=FALSE; 838 //int skipFileFlag=FALSE;
784 struct TarBallInfo tbInfo; 839 struct TarBallInfo tbInfo;
785 tbInfo.verboseFlag = verboseFlag; 840 tbInfo.verboseFlag = verboseFlag;
@@ -814,6 +869,10 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
814 errorFlag = TRUE; 869 errorFlag = TRUE;
815 } 870 }
816 } 871 }
872 /* Write two empty blocks to the end of the archive */
873 for (size=0; size<(2*TAR_BLOCK_SIZE); size++) {
874 write(tbInfo.tarFd, "\0", 1);
875 }
817 /* Hang up the tools, close up shop, head home */ 876 /* Hang up the tools, close up shop, head home */
818 close(tarFd); 877 close(tarFd);
819 if (errorFlag == TRUE) { 878 if (errorFlag == TRUE) {
diff --git a/busybox.c b/busybox.c
index c2477a537..9a48f4961 100644
--- a/busybox.c
+++ b/busybox.c
@@ -382,8 +382,8 @@ int busybox_main(int argc, char **argv)
382 fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); 382 fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
383 fprintf(stderr, " or: [function] [arguments]...\n\n"); 383 fprintf(stderr, " or: [function] [arguments]...\n\n");
384 fprintf(stderr, 384 fprintf(stderr,
385 "\tMost people will create a link to busybox for each\n" 385 "\tMost people will create a link to busybox for each function\n"
386 "\tfunction name, and busybox will act like whatever you invoke it as.\n"); 386 "\tname, and busybox will act like whatever you invoke it as.\n");
387 fprintf(stderr, "\nCurrently defined functions:\n"); 387 fprintf(stderr, "\nCurrently defined functions:\n");
388 388
389 while (a->name != 0) { 389 while (a->name != 0) {
diff --git a/kill.c b/kill.c
index 10343a150..260f4a074 100644
--- a/kill.c
+++ b/kill.c
@@ -1,6 +1,6 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini kill implementation for busybox 3 * Mini kill/killall implementation for busybox
4 * 4 *
5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. 5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6 * 6 *
diff --git a/procps/kill.c b/procps/kill.c
index 10343a150..260f4a074 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -1,6 +1,6 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini kill implementation for busybox 3 * Mini kill/killall implementation for busybox
4 * 4 *
5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. 5 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6 * 6 *
diff --git a/tar.c b/tar.c
index f9b3e1813..979821ec0 100644
--- a/tar.c
+++ b/tar.c
@@ -56,7 +56,8 @@
56 56
57static const char tar_usage[] = 57static const char tar_usage[] =
58 "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" 58 "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n"
59 "Create, extract, or list files from a tar file.\n\n" 59 "Create, extract, or list files from a tar file. Note that\n"
60 "this version of tar packs hard links as separate files.\n\n"
60 "Options:\n" 61 "Options:\n"
61 62
62 "\tc=create, x=extract, t=list contents, v=verbose,\n" 63 "\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -110,10 +111,10 @@ typedef struct TarHeader TarHeader;
110 111
111/* A few useful constants */ 112/* A few useful constants */
112#define TAR_MAGIC "ustar" /* ustar and a null */ 113#define TAR_MAGIC "ustar" /* ustar and a null */
113#define TAR_VERSION "00" /* 00 and no null */ 114//#define TAR_VERSION "00" /* 00 and no null */
115#define TAR_VERSION " " /* Be compatable with old GNU format */
114#define TAR_MAGIC_LEN 6 116#define TAR_MAGIC_LEN 6
115#define TAR_VERSION_LEN 2 117#define TAR_VERSION_LEN 2
116#define TAR_NAME_LEN 100
117#define TAR_BLOCK_SIZE 512 118#define TAR_BLOCK_SIZE 512
118 119
119/* A nice enum with all the possible tar file content types */ 120/* A nice enum with all the possible tar file content types */
@@ -366,7 +367,8 @@ tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag)
366 return; 367 return;
367 368
368 if (link(header->linkname, header->name) < 0) { 369 if (link(header->linkname, header->name) < 0) {
369 errorMsg("Error creating hard link '%s': %s\n", header->linkname, strerror(errno)); 370 errorMsg("Error creating hard link '%s' to '%s': %s\n",
371 header->name, header->linkname, strerror(errno));
370 return; 372 return;
371 } 373 }
372 374
@@ -382,7 +384,8 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag)
382 384
383#ifdef S_ISLNK 385#ifdef S_ISLNK
384 if (symlink(header->linkname, header->name) < 0) { 386 if (symlink(header->linkname, header->name) < 0) {
385 errorMsg("Error creating symlink '%s': %s\n", header->linkname, strerror(errno)); 387 errorMsg("Error creating symlink '%s' to '%s': %s\n",
388 header->name, header->linkname, strerror(errno));
386 return; 389 return;
387 } 390 }
388 /* Try to change ownership of the symlink. 391 /* Try to change ownership of the symlink.
@@ -644,18 +647,15 @@ typedef struct TarBallInfo TarBallInfo;
644static int putOctal (char *cp, int len, long value) 647static int putOctal (char *cp, int len, long value)
645{ 648{
646 int tempLength; 649 int tempLength;
647 char *tempString;
648 char tempBuffer[32]; 650 char tempBuffer[32];
651 char *tempString = tempBuffer;
649 652
650 /* Create a string of the specified length with an initial space, 653 /* Create a string of the specified length with an initial space,
651 * leading zeroes and the octal number, and a trailing null. */ 654 * leading zeroes and the octal number, and a trailing null. */
652 tempString = tempBuffer; 655 sprintf (tempString, "%0*lo", len - 1, value);
653
654 sprintf (tempString, " %0*lo", len - 2, value);
655
656 tempLength = strlen (tempString) + 1;
657 656
658 /* If the string is too large, suppress the leading space. */ 657 /* If the string is too large, suppress the leading space. */
658 tempLength = strlen (tempString) + 1;
659 if (tempLength > len) { 659 if (tempLength > len) {
660 tempLength--; 660 tempLength--;
661 tempString++; 661 tempString++;
@@ -677,10 +677,14 @@ static int putOctal (char *cp, int len, long value)
677 677
678/* Write out a tar header for the specified file/directory/whatever */ 678/* Write out a tar header for the specified file/directory/whatever */
679static int 679static int
680writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf) 680writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *statbuf)
681{ 681{
682 //int i; 682 long chksum=0;
683 //long chksum, sum; 683 struct TarHeader header;
684 const unsigned char *cp = (const unsigned char *) &header;
685 ssize_t size = sizeof(struct TarHeader);
686
687 memset( &header, 0, size);
684 688
685 if (*fileName=='/') { 689 if (*fileName=='/') {
686 static int alreadyWarned=FALSE; 690 static int alreadyWarned=FALSE;
@@ -688,66 +692,88 @@ writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *stat
688 errorMsg("tar: Removing leading '/' from member names\n"); 692 errorMsg("tar: Removing leading '/' from member names\n");
689 alreadyWarned=TRUE; 693 alreadyWarned=TRUE;
690 } 694 }
691 strcpy(header->name, fileName+1); 695 strcpy(header.name, fileName+1);
692 } 696 }
693 else { 697 else {
694 strcpy(header->name, fileName); 698 strcpy(header.name, fileName);
695 } 699 }
696 putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777); 700 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
697 putOctal(header->uid, sizeof(header->uid), statbuf->st_uid); 701 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
698 putOctal(header->gid, sizeof(header->gid), statbuf->st_gid); 702 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
699 putOctal(header->size, sizeof(header->size), statbuf->st_size); 703 putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */
700 putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime); 704 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
701 705 strncpy(header.magic, TAR_MAGIC TAR_VERSION,
706 TAR_MAGIC_LEN + TAR_VERSION_LEN );
707
708 my_getpwuid(header.uname, statbuf->st_uid);
709 /* Put some sort of sane fallback in place... */
710 if (! *header.uname)
711 strncpy(header.uname, "root", 5);
712 my_getgrgid(header.gname, statbuf->st_gid);
713 if (! *header.uname)
714 strncpy(header.uname, "root", 5);
715
716 // FIXME: (or most likely not) I break Hard Links
702 if (S_ISLNK(statbuf->st_mode)) { 717 if (S_ISLNK(statbuf->st_mode)) {
703 header->typeflag = LNKTYPE; 718 char buffer[BUFSIZ];
704 // TODO -- Handle SYMTYPE 719 header.typeflag = SYMTYPE;
720 if ( readlink(fileName, buffer, sizeof(buffer) - 1) < 0) {
721 errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
722 return ( FALSE);
723 }
724 strncpy(header.linkname, buffer, sizeof(header.linkname));
705 } else if (S_ISDIR(statbuf->st_mode)) { 725 } else if (S_ISDIR(statbuf->st_mode)) {
706 header->typeflag = DIRTYPE; 726 header.typeflag = DIRTYPE;
707 strncat(header->name, "/", sizeof(header->name)); 727 strncat(header.name, "/", sizeof(header.name));
708 } else if (S_ISCHR(statbuf->st_mode)) { 728 } else if (S_ISCHR(statbuf->st_mode)) {
709 header->typeflag = CHRTYPE; 729 header.typeflag = CHRTYPE;
710 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); 730 putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
711 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); 731 putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
712 } else if (S_ISBLK(statbuf->st_mode)) { 732 } else if (S_ISBLK(statbuf->st_mode)) {
713 header->typeflag = BLKTYPE; 733 header.typeflag = BLKTYPE;
714 putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); 734 putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
715 putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); 735 putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
716 } else if (S_ISFIFO(statbuf->st_mode)) { 736 } else if (S_ISFIFO(statbuf->st_mode)) {
717 header->typeflag = FIFOTYPE; 737 header.typeflag = FIFOTYPE;
718 } else if (S_ISLNK(statbuf->st_mode)) { 738 } else if (S_ISREG(statbuf->st_mode)) {
719 header->typeflag = LNKTYPE; 739 header.typeflag = REGTYPE;
720 } else if (S_ISLNK(statbuf->st_mode)) { 740 putOctal(header.size, sizeof(header.size), statbuf->st_size);
721 header->typeflag = REGTYPE;
722 } else { 741 } else {
742 errorMsg("tar: %s: Unknown file type\n", fileName);
723 return ( FALSE); 743 return ( FALSE);
724 } 744 }
725 return ( TRUE);
726
727#if 0
728 header->linkname = rawHeader->linkname;
729 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
730 header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
731 745
732 /* Write out the checksum */ 746 /* Calculate and store the checksum (i.e. the sum of all of the bytes of
733 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); 747 * the header). The checksum field must be filled with blanks for the
748 * calculation. The checksum field is formatted differently from the
749 * other fields: it has [6] digits, a null, then a space -- rather than
750 * digits, followed by a null like the other fields... */
751 memset(header.chksum, ' ', sizeof(header.chksum));
752 cp = (const unsigned char *) &header;
753 while (size-- > 0)
754 chksum += *cp++;
755 putOctal(header.chksum, 7, chksum);
756
757 /* Now write the header out to disk */
758 if ((size=fullWrite(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) {
759 errorMsg(io_error, fileName, strerror(errno));
760 return ( FALSE);
761 }
762 /* Pad the header up to the tar block size */
763 for (; size<TAR_BLOCK_SIZE; size++) {
764 write(tbInfo->tarFd, "\0", 1);
765 }
766 /* Now do the verbose thing (or not) */
767 if (tbInfo->verboseFlag==TRUE)
768 fprintf(stdout, "%s\n", header.name);
734 769
735 return ( TRUE); 770 return ( TRUE);
736#endif
737} 771}
738 772
739 773
740static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) 774static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
741{ 775{
742 int inputFileFd;
743 struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; 776 struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
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 777
752 /* It is against the rules to archive a socket */ 778 /* It is against the rules to archive a socket */
753 if (S_ISSOCK(statbuf->st_mode)) { 779 if (S_ISSOCK(statbuf->st_mode)) {
@@ -764,13 +790,41 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void*
764 return( TRUE); 790 return( TRUE);
765 } 791 }
766 792
767 memset( header, 0, sizeof(struct TarHeader)); 793 if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) {
768 if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) { 794 return( FALSE);
769 dprintf(tbInfo->tarFd, "%s", header);
770 } 795 }
771 /* Now do the verbose thing (or not) */ 796
772 if (tbInfo->verboseFlag==TRUE) 797 /* Now, if the file is a regular file, copy it out to the tarball */
773 fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name); 798 if (S_ISREG(statbuf->st_mode)) {
799 int inputFileFd;
800 char buffer[BUFSIZ];
801 ssize_t size=0, readSize=0;
802
803 /* open the file we want to archive, and make sure all is well */
804 if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
805 errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
806 return( FALSE);
807 }
808
809 /* write the file to the archive */
810 while ( (size = fullRead(inputFileFd, buffer, sizeof(buffer))) > 0 ) {
811 if (fullWrite(tbInfo->tarFd, buffer, size) != size ) {
812 /* Output file seems to have a problem */
813 errorMsg(io_error, fileName, strerror(errno));
814 return( FALSE);
815 }
816 readSize+=size;
817 }
818 if (size == -1) {
819 errorMsg(io_error, fileName, strerror(errno));
820 return( FALSE);
821 }
822 /* Pad the file up to the tar block size */
823 for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) {
824 write(tbInfo->tarFd, "\0", 1);
825 }
826 close( inputFileFd);
827 }
774 828
775 return( TRUE); 829 return( TRUE);
776} 830}
@@ -780,6 +834,7 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
780{ 834{
781 int tarFd=-1; 835 int tarFd=-1;
782 int errorFlag=FALSE; 836 int errorFlag=FALSE;
837 ssize_t size;
783 //int skipFileFlag=FALSE; 838 //int skipFileFlag=FALSE;
784 struct TarBallInfo tbInfo; 839 struct TarBallInfo tbInfo;
785 tbInfo.verboseFlag = verboseFlag; 840 tbInfo.verboseFlag = verboseFlag;
@@ -814,6 +869,10 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
814 errorFlag = TRUE; 869 errorFlag = TRUE;
815 } 870 }
816 } 871 }
872 /* Write two empty blocks to the end of the archive */
873 for (size=0; size<(2*TAR_BLOCK_SIZE); size++) {
874 write(tbInfo.tarFd, "\0", 1);
875 }
817 /* Hang up the tools, close up shop, head home */ 876 /* Hang up the tools, close up shop, head home */
818 close(tarFd); 877 close(tarFd);
819 if (errorFlag == TRUE) { 878 if (errorFlag == TRUE) {
diff --git a/utility.c b/utility.c
index 0d4799f2d..b91da4ce4 100644
--- a/utility.c
+++ b/utility.c
@@ -783,7 +783,7 @@ extern int parse_mode(const char *s, mode_t * theMode)
783 783
784 784
785 785
786#if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_PS) 786#if defined BB_CHMOD_CHOWN_CHGRP || defined BB_PS || defined BB_LS || defined BB_TAR
787 787
788/* Use this to avoid needing the glibc NSS stuff 788/* Use this to avoid needing the glibc NSS stuff
789 * This uses storage buf to hold things. 789 * This uses storage buf to hold things.
@@ -858,7 +858,7 @@ void my_getgrgid(char *group, gid_t gid)
858} 858}
859 859
860 860
861#endif /* BB_CHMOD_CHOWN_CHGRP || BB_PS */ 861#endif /* BB_CHMOD_CHOWN_CHGRP || BB_PS || BB_LS || BB_TAR */
862 862
863 863
864 864