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
This commit is contained in:
Erik Andersen
2000-04-05 01:00:52 +00:00
parent cbb0a4b40d
commit 5661fe078e
8 changed files with 245 additions and 178 deletions

53
TODO
View File

@@ -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 * Make insmod actually work
* dnsdomainname * dnsdomainname
* traceroute/netstat * traceroute/netstat
* rdate * rdate
* hwclock * hwclock
* killall
* stty * stty
* tr
* cut * cut
* expr (maybe?) (ash builtin?) * 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. busybox.defs.h is too big and hard to follow.
I either need to add a better build system (like the Linux kernel?) Perhaps I 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.
----------------------- -----------------------
-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 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? 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: Feature request:
/bin/busybox --install -s which makes all links to commands that it /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 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' 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 because there can be hard links from inside one argv/ to inside

View File

@@ -382,8 +382,8 @@ int busybox_main(int argc, char **argv)
fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
fprintf(stderr, " or: [function] [arguments]...\n\n"); fprintf(stderr, " or: [function] [arguments]...\n\n");
fprintf(stderr, fprintf(stderr,
"\tMost people will create a link to busybox for each\n" "\tMost people will create a link to busybox for each function\n"
"\tfunction name, and busybox will act like whatever you invoke it as.\n"); "\tname, and busybox will act like whatever you invoke it as.\n");
fprintf(stderr, "\nCurrently defined functions:\n"); fprintf(stderr, "\nCurrently defined functions:\n");
while (a->name != 0) { while (a->name != 0) {

View File

@@ -56,7 +56,8 @@
static const char tar_usage[] = static const char tar_usage[] =
"tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" "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" "Options:\n"
"\tc=create, x=extract, t=list contents, v=verbose,\n" "\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -110,10 +111,10 @@ typedef struct TarHeader TarHeader;
/* A few useful constants */ /* A few useful constants */
#define TAR_MAGIC "ustar" /* ustar and a null */ #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_MAGIC_LEN 6
#define TAR_VERSION_LEN 2 #define TAR_VERSION_LEN 2
#define TAR_NAME_LEN 100
#define TAR_BLOCK_SIZE 512 #define TAR_BLOCK_SIZE 512
/* A nice enum with all the possible tar file content types */ /* A nice enum with all the possible tar file content types */
@@ -366,7 +367,8 @@ tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag)
return; return;
if (link(header->linkname, header->name) < 0) { 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; return;
} }
@@ -382,7 +384,8 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag)
#ifdef S_ISLNK #ifdef S_ISLNK
if (symlink(header->linkname, header->name) < 0) { 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; return;
} }
/* Try to change ownership of the symlink. /* Try to change ownership of the symlink.
@@ -644,18 +647,15 @@ typedef struct TarBallInfo TarBallInfo;
static int putOctal (char *cp, int len, long value) static int putOctal (char *cp, int len, long value)
{ {
int tempLength; int tempLength;
char *tempString;
char tempBuffer[32]; char tempBuffer[32];
char *tempString = tempBuffer;
/* Create a string of the specified length with an initial space, /* Create a string of the specified length with an initial space,
* leading zeroes and the octal number, and a trailing null. */ * leading zeroes and the octal number, and a trailing null. */
tempString = tempBuffer; sprintf (tempString, "%0*lo", len - 1, value);
sprintf (tempString, " %0*lo", len - 2, value);
tempLength = strlen (tempString) + 1;
/* If the string is too large, suppress the leading space. */ /* If the string is too large, suppress the leading space. */
tempLength = strlen (tempString) + 1;
if (tempLength > len) { if (tempLength > len) {
tempLength--; tempLength--;
tempString++; 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 */ /* Write out a tar header for the specified file/directory/whatever */
static int 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=0;
//long chksum, sum; struct TarHeader header;
const unsigned char *cp = (const unsigned char *) &header;
ssize_t size = sizeof(struct TarHeader);
memset( &header, 0, size);
if (*fileName=='/') { if (*fileName=='/') {
static int alreadyWarned=FALSE; 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"); errorMsg("tar: Removing leading '/' from member names\n");
alreadyWarned=TRUE; alreadyWarned=TRUE;
} }
strcpy(header->name, fileName+1); strcpy(header.name, fileName+1);
} }
else { else {
strcpy(header->name, fileName); strcpy(header.name, fileName);
} }
putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
putOctal(header->uid, sizeof(header->uid), statbuf->st_uid); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
putOctal(header->gid, sizeof(header->gid), statbuf->st_gid); putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
putOctal(header->size, sizeof(header->size), statbuf->st_size); putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */
putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime); 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)) { if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = LNKTYPE; char buffer[BUFSIZ];
// TODO -- Handle SYMTYPE 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)) { } else if (S_ISDIR(statbuf->st_mode)) {
header->typeflag = DIRTYPE; header.typeflag = DIRTYPE;
strncat(header->name, "/", sizeof(header->name)); strncat(header.name, "/", sizeof(header.name));
} else if (S_ISCHR(statbuf->st_mode)) { } else if (S_ISCHR(statbuf->st_mode)) {
header->typeflag = CHRTYPE; header.typeflag = CHRTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
} else if (S_ISBLK(statbuf->st_mode)) { } else if (S_ISBLK(statbuf->st_mode)) {
header->typeflag = BLKTYPE; header.typeflag = BLKTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
} else if (S_ISFIFO(statbuf->st_mode)) { } else if (S_ISFIFO(statbuf->st_mode)) {
header->typeflag = FIFOTYPE; header.typeflag = FIFOTYPE;
} else if (S_ISLNK(statbuf->st_mode)) { } else if (S_ISREG(statbuf->st_mode)) {
header->typeflag = LNKTYPE; header.typeflag = REGTYPE;
} else if (S_ISLNK(statbuf->st_mode)) { putOctal(header.size, sizeof(header.size), statbuf->st_size);
header->typeflag = REGTYPE;
} else { } else {
errorMsg("tar: %s: Unknown file type\n", fileName);
return ( FALSE); return ( FALSE);
} }
return ( TRUE);
#if 0 /* Calculate and store the checksum (i.e. the sum of all of the bytes of
header->linkname = rawHeader->linkname; * the header). The checksum field must be filled with blanks for the
header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); * calculation. The checksum field is formatted differently from the
header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor)); * other fields: it has [6] digits, a null, then a space -- rather than
* digits, followed by a null like the other fields... */
/* Write out the checksum */ memset(header.chksum, ' ', sizeof(header.chksum));
chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->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 (; size<TAR_BLOCK_SIZE; size++) {
write(tbInfo->tarFd, "\0", 1);
}
/* Now do the verbose thing (or not) */
if (tbInfo->verboseFlag==TRUE)
fprintf(stdout, "%s\n", header.name);
return ( TRUE); return ( TRUE);
#endif
} }
static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
{ {
int inputFileFd;
struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; 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 */ /* It is against the rules to archive a socket */
if (S_ISSOCK(statbuf->st_mode)) { if (S_ISSOCK(statbuf->st_mode)) {
@@ -764,13 +790,41 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void*
return( TRUE); return( TRUE);
} }
memset( header, 0, sizeof(struct TarHeader)); if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) {
if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) { return( FALSE);
dprintf(tbInfo->tarFd, "%s", header);
} }
/* Now do the verbose thing (or not) */
if (tbInfo->verboseFlag==TRUE) /* Now, if the file is a regular file, copy it out to the tarball */
fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name); 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); return( TRUE);
} }
@@ -780,6 +834,7 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
{ {
int tarFd=-1; int tarFd=-1;
int errorFlag=FALSE; int errorFlag=FALSE;
ssize_t size;
//int skipFileFlag=FALSE; //int skipFileFlag=FALSE;
struct TarBallInfo tbInfo; struct TarBallInfo tbInfo;
tbInfo.verboseFlag = verboseFlag; tbInfo.verboseFlag = verboseFlag;
@@ -814,6 +869,10 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
errorFlag = TRUE; 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 */ /* Hang up the tools, close up shop, head home */
close(tarFd); close(tarFd);
if (errorFlag == TRUE) { if (errorFlag == TRUE) {

View File

@@ -382,8 +382,8 @@ int busybox_main(int argc, char **argv)
fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
fprintf(stderr, " or: [function] [arguments]...\n\n"); fprintf(stderr, " or: [function] [arguments]...\n\n");
fprintf(stderr, fprintf(stderr,
"\tMost people will create a link to busybox for each\n" "\tMost people will create a link to busybox for each function\n"
"\tfunction name, and busybox will act like whatever you invoke it as.\n"); "\tname, and busybox will act like whatever you invoke it as.\n");
fprintf(stderr, "\nCurrently defined functions:\n"); fprintf(stderr, "\nCurrently defined functions:\n");
while (a->name != 0) { while (a->name != 0) {

2
kill.c
View File

@@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4: */ /* vi: set sw=4 ts=4: */
/* /*
* Mini kill implementation for busybox * Mini kill/killall implementation for busybox
* *
* Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
* *

View File

@@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4: */ /* vi: set sw=4 ts=4: */
/* /*
* Mini kill implementation for busybox * Mini kill/killall implementation for busybox
* *
* Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
* *

177
tar.c
View File

@@ -56,7 +56,8 @@
static const char tar_usage[] = static const char tar_usage[] =
"tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" "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" "Options:\n"
"\tc=create, x=extract, t=list contents, v=verbose,\n" "\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -110,10 +111,10 @@ typedef struct TarHeader TarHeader;
/* A few useful constants */ /* A few useful constants */
#define TAR_MAGIC "ustar" /* ustar and a null */ #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_MAGIC_LEN 6
#define TAR_VERSION_LEN 2 #define TAR_VERSION_LEN 2
#define TAR_NAME_LEN 100
#define TAR_BLOCK_SIZE 512 #define TAR_BLOCK_SIZE 512
/* A nice enum with all the possible tar file content types */ /* A nice enum with all the possible tar file content types */
@@ -366,7 +367,8 @@ tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag)
return; return;
if (link(header->linkname, header->name) < 0) { 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; return;
} }
@@ -382,7 +384,8 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag)
#ifdef S_ISLNK #ifdef S_ISLNK
if (symlink(header->linkname, header->name) < 0) { 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; return;
} }
/* Try to change ownership of the symlink. /* Try to change ownership of the symlink.
@@ -644,18 +647,15 @@ typedef struct TarBallInfo TarBallInfo;
static int putOctal (char *cp, int len, long value) static int putOctal (char *cp, int len, long value)
{ {
int tempLength; int tempLength;
char *tempString;
char tempBuffer[32]; char tempBuffer[32];
char *tempString = tempBuffer;
/* Create a string of the specified length with an initial space, /* Create a string of the specified length with an initial space,
* leading zeroes and the octal number, and a trailing null. */ * leading zeroes and the octal number, and a trailing null. */
tempString = tempBuffer; sprintf (tempString, "%0*lo", len - 1, value);
sprintf (tempString, " %0*lo", len - 2, value);
tempLength = strlen (tempString) + 1;
/* If the string is too large, suppress the leading space. */ /* If the string is too large, suppress the leading space. */
tempLength = strlen (tempString) + 1;
if (tempLength > len) { if (tempLength > len) {
tempLength--; tempLength--;
tempString++; 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 */ /* Write out a tar header for the specified file/directory/whatever */
static int 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=0;
//long chksum, sum; struct TarHeader header;
const unsigned char *cp = (const unsigned char *) &header;
ssize_t size = sizeof(struct TarHeader);
memset( &header, 0, size);
if (*fileName=='/') { if (*fileName=='/') {
static int alreadyWarned=FALSE; 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"); errorMsg("tar: Removing leading '/' from member names\n");
alreadyWarned=TRUE; alreadyWarned=TRUE;
} }
strcpy(header->name, fileName+1); strcpy(header.name, fileName+1);
} }
else { else {
strcpy(header->name, fileName); strcpy(header.name, fileName);
} }
putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
putOctal(header->uid, sizeof(header->uid), statbuf->st_uid); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
putOctal(header->gid, sizeof(header->gid), statbuf->st_gid); putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
putOctal(header->size, sizeof(header->size), statbuf->st_size); putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */
putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime); 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)) { if (S_ISLNK(statbuf->st_mode)) {
header->typeflag = LNKTYPE; char buffer[BUFSIZ];
// TODO -- Handle SYMTYPE 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)) { } else if (S_ISDIR(statbuf->st_mode)) {
header->typeflag = DIRTYPE; header.typeflag = DIRTYPE;
strncat(header->name, "/", sizeof(header->name)); strncat(header.name, "/", sizeof(header.name));
} else if (S_ISCHR(statbuf->st_mode)) { } else if (S_ISCHR(statbuf->st_mode)) {
header->typeflag = CHRTYPE; header.typeflag = CHRTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
} else if (S_ISBLK(statbuf->st_mode)) { } else if (S_ISBLK(statbuf->st_mode)) {
header->typeflag = BLKTYPE; header.typeflag = BLKTYPE;
putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
} else if (S_ISFIFO(statbuf->st_mode)) { } else if (S_ISFIFO(statbuf->st_mode)) {
header->typeflag = FIFOTYPE; header.typeflag = FIFOTYPE;
} else if (S_ISLNK(statbuf->st_mode)) { } else if (S_ISREG(statbuf->st_mode)) {
header->typeflag = LNKTYPE; header.typeflag = REGTYPE;
} else if (S_ISLNK(statbuf->st_mode)) { putOctal(header.size, sizeof(header.size), statbuf->st_size);
header->typeflag = REGTYPE;
} else { } else {
errorMsg("tar: %s: Unknown file type\n", fileName);
return ( FALSE); return ( FALSE);
} }
return ( TRUE);
#if 0 /* Calculate and store the checksum (i.e. the sum of all of the bytes of
header->linkname = rawHeader->linkname; * the header). The checksum field must be filled with blanks for the
header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); * calculation. The checksum field is formatted differently from the
header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor)); * other fields: it has [6] digits, a null, then a space -- rather than
* digits, followed by a null like the other fields... */
/* Write out the checksum */ memset(header.chksum, ' ', sizeof(header.chksum));
chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->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 (; size<TAR_BLOCK_SIZE; size++) {
write(tbInfo->tarFd, "\0", 1);
}
/* Now do the verbose thing (or not) */
if (tbInfo->verboseFlag==TRUE)
fprintf(stdout, "%s\n", header.name);
return ( TRUE); return ( TRUE);
#endif
} }
static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
{ {
int inputFileFd;
struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; 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 */ /* It is against the rules to archive a socket */
if (S_ISSOCK(statbuf->st_mode)) { if (S_ISSOCK(statbuf->st_mode)) {
@@ -764,13 +790,41 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void*
return( TRUE); return( TRUE);
} }
memset( header, 0, sizeof(struct TarHeader)); if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) {
if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) { return( FALSE);
dprintf(tbInfo->tarFd, "%s", header);
} }
/* Now do the verbose thing (or not) */
if (tbInfo->verboseFlag==TRUE) /* Now, if the file is a regular file, copy it out to the tarball */
fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name); 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); return( TRUE);
} }
@@ -780,6 +834,7 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
{ {
int tarFd=-1; int tarFd=-1;
int errorFlag=FALSE; int errorFlag=FALSE;
ssize_t size;
//int skipFileFlag=FALSE; //int skipFileFlag=FALSE;
struct TarBallInfo tbInfo; struct TarBallInfo tbInfo;
tbInfo.verboseFlag = verboseFlag; tbInfo.verboseFlag = verboseFlag;
@@ -814,6 +869,10 @@ static int writeTarFile(const char* tarName, int tostdoutFlag,
errorFlag = TRUE; 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 */ /* Hang up the tools, close up shop, head home */
close(tarFd); close(tarFd);
if (errorFlag == TRUE) { if (errorFlag == TRUE) {

View File

@@ -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 /* Use this to avoid needing the glibc NSS stuff
* This uses storage buf to hold things. * 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 */