From 5661fe078eed752780b11f3f4fdd33bbd76a6c5e Mon Sep 17 00:00:00 2001 From: Erik Andersen Date: Wed, 5 Apr 2000 01:00:52 +0000 Subject: [PATCH] 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 --- TODO | 53 +------------- applets/busybox.c | 4 +- archival/tar.c | 179 ++++++++++++++++++++++++++++++---------------- busybox.c | 4 +- kill.c | 2 +- procps/kill.c | 2 +- tar.c | 179 ++++++++++++++++++++++++++++++---------------- utility.c | 4 +- 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. ----------- -* Allow tar to create archives with sockets, devices, and other special files * Make insmod actually work * dnsdomainname * traceroute/netstat * rdate * hwclock -* killall * stty -* tr * cut * expr (maybe?) (ash builtin?) @@ -40,58 +37,17 @@ and then start with the biggest things and make them smaller... busybox.defs.h is too big and hard to follow. -I either need to add a better build system (like the Linux kernel?) -or I need to split up busybox.defs.h into coherent chunks (i.e. -busybox.defs.h just has a bunch of: - -#include "fileutils.h" -#include "shellutils.h" - -which would then have smaller sets of #defines... -Hmm. Needs to be carefully thought out. +Perhaps I need to add a better build system (like the Linux kernel?) ----------------------- --rw-r--r-- 1000/1000 4398 2000-01-06 21:55 uniq.c --rw-r--r-- 1000/1000 1568 1999-10-20 18:08 update.c --rw-r----- 0/1000 1168 2000-01-29 21:03 update.o --rw-r--r-- 1000/1000 22820 2000-01-05 11:36 utility.c --rw-r----- 0/1000 7372 2000-01-29 21:03 utility.o -tar: Skipping to next file header -tar: Skipping to next file header -tar: Archive - EOF not on block boundary -tar: Error is not recoverable: exiting now - - -#1 You are storing by id instead of name like normal tar. Did you realize this? -(or am I missing some compile option? )ctar did not do this, and I don't think -it's a good idea for LRP. - -#2 -ctar did not produce the EOF error like your tar does. I believe you need to -pad the end of the archive with at least 2 tarsized (512byte) blocks. (I -think???) - -#3 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? ----------------------- -cd /mnt -mkdir BACKUP -mv * BACKUP - -Today, "mv" behaved as a cp -a and my disk becomed full. It does not -work properly either when renaming a directory into something else -(it produces a lot of disk activity when doing this). - - ------------------------ - - Feature request: /bin/busybox --install -s which makes all links to commands that it @@ -114,13 +70,6 @@ I'll add this to the TODO list, ----------------------- - In utility.c:copyFile: It uses followLinks for both source and - destination files... is that right for `mv'? Will need to revisit - the GNU, freeBSD, and MINIX versions for this... Should read the - Unix98 and POSIX specs also. - ------------------------ - I think that the add_inode &c in utility.c needs to also stow the st_dev field, and that du.c should NOT call `reset_inode_list' 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) fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, " or: [function] [arguments]...\n\n"); fprintf(stderr, - "\tMost people will create a link to busybox for each\n" - "\tfunction name, and busybox will act like whatever you invoke it as.\n"); + "\tMost people will create a link to busybox for each function\n" + "\tname, and busybox will act like whatever you invoke it as.\n"); fprintf(stderr, "\nCurrently defined functions:\n"); 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 @@ static const char tar_usage[] = "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" - "Create, extract, or list files from a tar 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" @@ -110,10 +111,10 @@ typedef struct TarHeader TarHeader; /* A few useful constants */ #define TAR_MAGIC "ustar" /* ustar and a null */ -#define TAR_VERSION "00" /* 00 and no null */ +//#define TAR_VERSION "00" /* 00 and no null */ +#define TAR_VERSION " " /* Be compatable with old GNU format */ #define TAR_MAGIC_LEN 6 #define TAR_VERSION_LEN 2 -#define TAR_NAME_LEN 100 #define TAR_BLOCK_SIZE 512 /* A nice enum with all the possible tar file content types */ @@ -366,7 +367,8 @@ tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag) return; if (link(header->linkname, header->name) < 0) { - errorMsg("Error creating hard link '%s': %s\n", header->linkname, strerror(errno)); + errorMsg("Error creating hard link '%s' to '%s': %s\n", + header->name, header->linkname, strerror(errno)); return; } @@ -382,7 +384,8 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) #ifdef S_ISLNK if (symlink(header->linkname, header->name) < 0) { - errorMsg("Error creating symlink '%s': %s\n", header->linkname, strerror(errno)); + errorMsg("Error creating symlink '%s' to '%s': %s\n", + header->name, header->linkname, strerror(errno)); return; } /* Try to change ownership of the symlink. @@ -644,18 +647,15 @@ typedef struct TarBallInfo TarBallInfo; static int putOctal (char *cp, int len, long value) { int tempLength; - char *tempString; char tempBuffer[32]; + char *tempString = tempBuffer; /* Create a string of the specified length with an initial space, * leading zeroes and the octal number, and a trailing null. */ - tempString = tempBuffer; - - sprintf (tempString, " %0*lo", len - 2, value); - - tempLength = strlen (tempString) + 1; + sprintf (tempString, "%0*lo", len - 1, value); /* If the string is too large, suppress the leading space. */ + tempLength = strlen (tempString) + 1; if (tempLength > len) { tempLength--; tempString++; @@ -677,10 +677,14 @@ static int putOctal (char *cp, int len, long value) /* Write out a tar header for the specified file/directory/whatever */ static int -writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf) +writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *statbuf) { - //int i; - //long chksum, sum; + long chksum=0; + struct TarHeader header; + const unsigned char *cp = (const unsigned char *) &header; + ssize_t size = sizeof(struct TarHeader); + + memset( &header, 0, size); if (*fileName=='/') { static int alreadyWarned=FALSE; @@ -688,66 +692,88 @@ writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *stat errorMsg("tar: Removing leading '/' from member names\n"); alreadyWarned=TRUE; } - strcpy(header->name, fileName+1); + strcpy(header.name, fileName+1); } else { - strcpy(header->name, fileName); + 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); - + putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); + putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); + putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); + putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */ + putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); + strncpy(header.magic, TAR_MAGIC TAR_VERSION, + TAR_MAGIC_LEN + TAR_VERSION_LEN ); + + my_getpwuid(header.uname, statbuf->st_uid); + /* Put some sort of sane fallback in place... */ + if (! *header.uname) + strncpy(header.uname, "root", 5); + my_getgrgid(header.gname, statbuf->st_gid); + if (! *header.uname) + strncpy(header.uname, "root", 5); + + // FIXME: (or most likely not) I break Hard Links if (S_ISLNK(statbuf->st_mode)) { - header->typeflag = LNKTYPE; - // TODO -- Handle SYMTYPE + char buffer[BUFSIZ]; + header.typeflag = SYMTYPE; + if ( readlink(fileName, buffer, sizeof(buffer) - 1) < 0) { + errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno)); + return ( FALSE); + } + strncpy(header.linkname, buffer, sizeof(header.linkname)); } else if (S_ISDIR(statbuf->st_mode)) { - header->typeflag = DIRTYPE; - strncat(header->name, "/", sizeof(header->name)); + 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)); + 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)); + 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; + header.typeflag = FIFOTYPE; + } else if (S_ISREG(statbuf->st_mode)) { + header.typeflag = REGTYPE; + putOctal(header.size, sizeof(header.size), statbuf->st_size); } else { + errorMsg("tar: %s: Unknown file type\n", fileName); return ( FALSE); } - return ( TRUE); - -#if 0 - header->linkname = rawHeader->linkname; - header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); - header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor)); - /* Write out the checksum */ - chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); + /* Calculate and store the checksum (i.e. the sum of all of the bytes of + * the header). The checksum field must be filled with blanks for the + * calculation. The checksum field is formatted differently from the + * other fields: it has [6] digits, a null, then a space -- rather than + * digits, followed by a null like the other fields... */ + memset(header.chksum, ' ', sizeof(header.chksum)); + cp = (const unsigned char *) &header; + while (size-- > 0) + chksum += *cp++; + putOctal(header.chksum, 7, chksum); + + /* Now write the header out to disk */ + if ((size=fullWrite(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) { + errorMsg(io_error, fileName, strerror(errno)); + return ( FALSE); + } + /* Pad the header up to the tar block size */ + for (; sizetarFd, "\0", 1); + } + /* Now do the verbose thing (or not) */ + if (tbInfo->verboseFlag==TRUE) + fprintf(stdout, "%s\n", header.name); return ( TRUE); -#endif } static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) { - int inputFileFd; 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); - } /* It is against the rules to archive a socket */ if (S_ISSOCK(statbuf->st_mode)) { @@ -764,13 +790,41 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* return( TRUE); } - memset( header, 0, sizeof(struct TarHeader)); - if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) { - dprintf(tbInfo->tarFd, "%s", header); + if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) { + return( FALSE); } - /* Now do the verbose thing (or not) */ - if (tbInfo->verboseFlag==TRUE) - fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name); + + /* Now, if the file is a regular file, copy it out to the tarball */ + if (S_ISREG(statbuf->st_mode)) { + int inputFileFd; + char buffer[BUFSIZ]; + ssize_t size=0, readSize=0; + + /* 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( FALSE); + } + + /* write the file to the archive */ + while ( (size = fullRead(inputFileFd, buffer, sizeof(buffer))) > 0 ) { + if (fullWrite(tbInfo->tarFd, buffer, size) != size ) { + /* Output file seems to have a problem */ + errorMsg(io_error, fileName, strerror(errno)); + return( FALSE); + } + readSize+=size; + } + if (size == -1) { + errorMsg(io_error, fileName, strerror(errno)); + return( FALSE); + } + /* Pad the file up to the tar block size */ + for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) { + write(tbInfo->tarFd, "\0", 1); + } + close( inputFileFd); + } return( TRUE); } @@ -780,6 +834,7 @@ static int writeTarFile(const char* tarName, int tostdoutFlag, { int tarFd=-1; int errorFlag=FALSE; + ssize_t size; //int skipFileFlag=FALSE; struct TarBallInfo tbInfo; tbInfo.verboseFlag = verboseFlag; @@ -814,6 +869,10 @@ static int writeTarFile(const char* tarName, int tostdoutFlag, errorFlag = TRUE; } } + /* Write two empty blocks to the end of the archive */ + for (size=0; size<(2*TAR_BLOCK_SIZE); size++) { + write(tbInfo.tarFd, "\0", 1); + } /* Hang up the tools, close up shop, head home */ close(tarFd); 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) fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, " or: [function] [arguments]...\n\n"); fprintf(stderr, - "\tMost people will create a link to busybox for each\n" - "\tfunction name, and busybox will act like whatever you invoke it as.\n"); + "\tMost people will create a link to busybox for each function\n" + "\tname, and busybox will act like whatever you invoke it as.\n"); fprintf(stderr, "\nCurrently defined functions:\n"); 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 @@ /* vi: set sw=4 ts=4: */ /* - * Mini kill implementation for busybox + * Mini kill/killall implementation for busybox * * Copyright (C) 1995, 1996 by Bruce Perens . * 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 @@ /* vi: set sw=4 ts=4: */ /* - * Mini kill implementation for busybox + * Mini kill/killall implementation for busybox * * Copyright (C) 1995, 1996 by Bruce Perens . * diff --git a/tar.c b/tar.c index f9b3e1813..979821ec0 100644 --- a/tar.c +++ b/tar.c @@ -56,7 +56,8 @@ static const char tar_usage[] = "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" - "Create, extract, or list files from a tar 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" @@ -110,10 +111,10 @@ typedef struct TarHeader TarHeader; /* A few useful constants */ #define TAR_MAGIC "ustar" /* ustar and a null */ -#define TAR_VERSION "00" /* 00 and no null */ +//#define TAR_VERSION "00" /* 00 and no null */ +#define TAR_VERSION " " /* Be compatable with old GNU format */ #define TAR_MAGIC_LEN 6 #define TAR_VERSION_LEN 2 -#define TAR_NAME_LEN 100 #define TAR_BLOCK_SIZE 512 /* A nice enum with all the possible tar file content types */ @@ -366,7 +367,8 @@ tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag) return; if (link(header->linkname, header->name) < 0) { - errorMsg("Error creating hard link '%s': %s\n", header->linkname, strerror(errno)); + errorMsg("Error creating hard link '%s' to '%s': %s\n", + header->name, header->linkname, strerror(errno)); return; } @@ -382,7 +384,8 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) #ifdef S_ISLNK if (symlink(header->linkname, header->name) < 0) { - errorMsg("Error creating symlink '%s': %s\n", header->linkname, strerror(errno)); + errorMsg("Error creating symlink '%s' to '%s': %s\n", + header->name, header->linkname, strerror(errno)); return; } /* Try to change ownership of the symlink. @@ -644,18 +647,15 @@ typedef struct TarBallInfo TarBallInfo; static int putOctal (char *cp, int len, long value) { int tempLength; - char *tempString; char tempBuffer[32]; + char *tempString = tempBuffer; /* Create a string of the specified length with an initial space, * leading zeroes and the octal number, and a trailing null. */ - tempString = tempBuffer; - - sprintf (tempString, " %0*lo", len - 2, value); - - tempLength = strlen (tempString) + 1; + sprintf (tempString, "%0*lo", len - 1, value); /* If the string is too large, suppress the leading space. */ + tempLength = strlen (tempString) + 1; if (tempLength > len) { tempLength--; tempString++; @@ -677,10 +677,14 @@ static int putOctal (char *cp, int len, long value) /* Write out a tar header for the specified file/directory/whatever */ static int -writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf) +writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *statbuf) { - //int i; - //long chksum, sum; + long chksum=0; + struct TarHeader header; + const unsigned char *cp = (const unsigned char *) &header; + ssize_t size = sizeof(struct TarHeader); + + memset( &header, 0, size); if (*fileName=='/') { static int alreadyWarned=FALSE; @@ -688,66 +692,88 @@ writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *stat errorMsg("tar: Removing leading '/' from member names\n"); alreadyWarned=TRUE; } - strcpy(header->name, fileName+1); + strcpy(header.name, fileName+1); } else { - strcpy(header->name, fileName); + 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); - + putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); + putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); + putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); + putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */ + putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); + strncpy(header.magic, TAR_MAGIC TAR_VERSION, + TAR_MAGIC_LEN + TAR_VERSION_LEN ); + + my_getpwuid(header.uname, statbuf->st_uid); + /* Put some sort of sane fallback in place... */ + if (! *header.uname) + strncpy(header.uname, "root", 5); + my_getgrgid(header.gname, statbuf->st_gid); + if (! *header.uname) + strncpy(header.uname, "root", 5); + + // FIXME: (or most likely not) I break Hard Links if (S_ISLNK(statbuf->st_mode)) { - header->typeflag = LNKTYPE; - // TODO -- Handle SYMTYPE + char buffer[BUFSIZ]; + header.typeflag = SYMTYPE; + if ( readlink(fileName, buffer, sizeof(buffer) - 1) < 0) { + errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno)); + return ( FALSE); + } + strncpy(header.linkname, buffer, sizeof(header.linkname)); } else if (S_ISDIR(statbuf->st_mode)) { - header->typeflag = DIRTYPE; - strncat(header->name, "/", sizeof(header->name)); + 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)); + 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)); + 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; + header.typeflag = FIFOTYPE; + } else if (S_ISREG(statbuf->st_mode)) { + header.typeflag = REGTYPE; + putOctal(header.size, sizeof(header.size), statbuf->st_size); } else { + errorMsg("tar: %s: Unknown file type\n", fileName); return ( FALSE); } - return ( TRUE); - -#if 0 - header->linkname = rawHeader->linkname; - header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); - header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor)); - /* Write out the checksum */ - chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); + /* Calculate and store the checksum (i.e. the sum of all of the bytes of + * the header). The checksum field must be filled with blanks for the + * calculation. The checksum field is formatted differently from the + * other fields: it has [6] digits, a null, then a space -- rather than + * digits, followed by a null like the other fields... */ + memset(header.chksum, ' ', sizeof(header.chksum)); + cp = (const unsigned char *) &header; + while (size-- > 0) + chksum += *cp++; + putOctal(header.chksum, 7, chksum); + + /* Now write the header out to disk */ + if ((size=fullWrite(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) { + errorMsg(io_error, fileName, strerror(errno)); + return ( FALSE); + } + /* Pad the header up to the tar block size */ + for (; sizetarFd, "\0", 1); + } + /* Now do the verbose thing (or not) */ + if (tbInfo->verboseFlag==TRUE) + fprintf(stdout, "%s\n", header.name); return ( TRUE); -#endif } static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) { - int inputFileFd; 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); - } /* It is against the rules to archive a socket */ if (S_ISSOCK(statbuf->st_mode)) { @@ -764,13 +790,41 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* return( TRUE); } - memset( header, 0, sizeof(struct TarHeader)); - if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) { - dprintf(tbInfo->tarFd, "%s", header); + if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) { + return( FALSE); } - /* Now do the verbose thing (or not) */ - if (tbInfo->verboseFlag==TRUE) - fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name); + + /* Now, if the file is a regular file, copy it out to the tarball */ + if (S_ISREG(statbuf->st_mode)) { + int inputFileFd; + char buffer[BUFSIZ]; + ssize_t size=0, readSize=0; + + /* 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( FALSE); + } + + /* write the file to the archive */ + while ( (size = fullRead(inputFileFd, buffer, sizeof(buffer))) > 0 ) { + if (fullWrite(tbInfo->tarFd, buffer, size) != size ) { + /* Output file seems to have a problem */ + errorMsg(io_error, fileName, strerror(errno)); + return( FALSE); + } + readSize+=size; + } + if (size == -1) { + errorMsg(io_error, fileName, strerror(errno)); + return( FALSE); + } + /* Pad the file up to the tar block size */ + for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) { + write(tbInfo->tarFd, "\0", 1); + } + close( inputFileFd); + } return( TRUE); } @@ -780,6 +834,7 @@ static int writeTarFile(const char* tarName, int tostdoutFlag, { int tarFd=-1; int errorFlag=FALSE; + ssize_t size; //int skipFileFlag=FALSE; struct TarBallInfo tbInfo; tbInfo.verboseFlag = verboseFlag; @@ -814,6 +869,10 @@ static int writeTarFile(const char* tarName, int tostdoutFlag, errorFlag = TRUE; } } + /* Write two empty blocks to the end of the archive */ + for (size=0; size<(2*TAR_BLOCK_SIZE); size++) { + write(tbInfo.tarFd, "\0", 1); + } /* Hang up the tools, close up shop, head home */ close(tarFd); 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) -#if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_PS) +#if defined BB_CHMOD_CHOWN_CHGRP || defined BB_PS || defined BB_LS || defined BB_TAR /* Use this to avoid needing the glibc NSS stuff * This uses storage buf to hold things. @@ -858,7 +858,7 @@ void my_getgrgid(char *group, gid_t gid) } -#endif /* BB_CHMOD_CHOWN_CHGRP || BB_PS */ +#endif /* BB_CHMOD_CHOWN_CHGRP || BB_PS || BB_LS || BB_TAR */ -- 2.25.1