#if defined BB_FEATURE_TAR_EXCLUDE
"[--exclude File] "
#endif
- "[-f tarFile] [FILE] ...\n\n"
- "Create, extract, or list files from a tar file. Note that\n"
+ "[-f tarFile] [FILE] ...\n"
+#ifndef BB_FEATURE_TRIVIAL_HELP
+ "\nCreate, extract, or list files from a tar file. Note that\n"
"this version of tar treats hard links as separate files.\n\n"
"Main operation mode:\n"
#ifdef BB_FEATURE_TAR_CREATE
#endif
"\nInformative output:\n"
"\tv\t\tverbosely list files processed\n"
+#endif
;
/* Tar file constants */
#if defined BB_FEATURE_TAR_EXCLUDE
int excludeListSize=0;
#endif
- const char *tarName=NULL;
+ const char *tarName="-";
int listFlag = FALSE;
int extractFlag = FALSE;
int createFlag = FALSE;
usage(tar_usage);
/* Parse any options */
- while (--argc > 0 && **(++argv) == '-') {
+ while (--argc > 0 && strspn(*(++argv), "-cxt") >0 ) {
stopIt=FALSE;
- while (stopIt==FALSE && *(++(*argv))) {
+ while (stopIt==FALSE && *argv && **argv) {
switch (**argv) {
case 'f':
if (--argc == 0) {
fatalError( "Option requires an argument: No file specified\n");
}
- if (tarName != NULL)
+ if (*tarName != '-')
fatalError( "Only one 'f' option allowed\n");
tarName = *(++argv);
if (tarName == NULL)
fatalError( "Option requires an argument: No file specified\n");
+ if (!strcmp(tarName, "-"))
+ tostdoutFlag = TRUE;
stopIt=TRUE;
break;
break;
}
#endif
+ if (strcmp(*argv, "-help")==0) {
+ usage(tar_usage);
+ }
break;
default:
fatalError( "Unknown tar flag '%c'\n"
"Try `tar --help' for more information\n", **argv);
}
+ ++(*argv);
}
}
#else
exit(writeTarFile(tarName, tostdoutFlag, verboseFlag, argc, argv, excludeList));
#endif
- } else {
+ }
+ if (listFlag == TRUE || extractFlag == TRUE) {
exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag, excludeList));
}
/* Open the file to be written, if a file is supposed to be written */
if (extractFlag==TRUE && tostdoutFlag==FALSE) {
- if ((outFd=open(header->name, O_CREAT|O_TRUNC|O_WRONLY, header->mode & ~S_IFMT)) < 0)
- errorMsg(io_error, header->name, strerror(errno));
/* Create the path to the file, just in case it isn't there...
* This should not screw up path permissions or anything. */
createPath(header->name, 0777);
+ if ((outFd=open(header->name, O_CREAT|O_TRUNC|O_WRONLY,
+ header->mode & ~S_IFMT)) < 0) {
+ errorMsg(io_error, header->name, strerror(errno));
+ return( FALSE);
+ }
}
/* Write out the file, if we are supposed to be doing that */
}
if ( (readSize = fullRead(header->tarFd, buffer, readSize)) <= 0 ) {
/* Tarball seems to have a problem */
- errorMsg("tar: Unexpected EOF in archive\n");
+ errorMsg("Unexpected EOF in archive\n");
return( FALSE);
}
if ( readSize < writeSize )
return( TRUE);
if (createPath(header->name, header->mode) != TRUE) {
- errorMsg("tar: %s: Cannot mkdir: %s\n",
+ errorMsg("%s: Cannot mkdir: %s\n",
header->name, strerror(errno));
return( FALSE);
}
return( TRUE);
if (link(header->linkname, header->name) < 0) {
- errorMsg("tar: %s: Cannot create hard link to '%s': %s\n",
+ errorMsg("%s: Cannot create hard link to '%s': %s\n",
header->name, header->linkname, strerror(errno));
return( FALSE);
}
#ifdef S_ISLNK
if (symlink(header->linkname, header->name) < 0) {
- errorMsg("tar: %s: Cannot create symlink to '%s': %s\n",
+ errorMsg("%s: Cannot create symlink to '%s': %s\n",
header->name, header->linkname, strerror(errno));
return( FALSE);
}
/* Do not change permissions or date on symlink,
* since it changes the pointed to file instead. duh. */
#else
- errorMsg("tar: %s: Cannot create symlink to '%s': %s\n",
+ errorMsg("%s: Cannot create symlink to '%s': %s\n",
header->name, header->linkname,
"symlinks not supported");
#endif
if (S_ISCHR(header->mode) || S_ISBLK(header->mode) || S_ISSOCK(header->mode)) {
if (mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)) < 0) {
- errorMsg("tar: %s: Cannot mknod: %s\n",
+ errorMsg("%s: Cannot mknod: %s\n",
header->name, strerror(errno));
return( FALSE);
}
} else if (S_ISFIFO(header->mode)) {
if (mkfifo(header->name, header->mode) < 0) {
- errorMsg("tar: %s: Cannot mkfifo: %s\n",
+ errorMsg("%s: Cannot mkfifo: %s\n",
header->name, strerror(errno));
return( FALSE);
}
++*(header->name);
if (alreadyWarned == FALSE) {
- errorMsg("tar: Removing leading '/' from member names\n");
+ errorMsg("Removing leading '/' from member names\n");
alreadyWarned = TRUE;
}
}
}
/* Remove any clutter lying in our way */
- unlink( header.name);
+ if (extractFlag == TRUE) /* .. but only if we are extracting (as */
+ unlink( header.name); /* opposed to listing) (rob@sysgo.de) */
/* If we got here, we can be certain we have a legitimate
* header to work with. So work with it. */
return ( FALSE);
}
else if (errorFlag==TRUE) {
- errorMsg( "tar: Error exit delayed from previous errors\n");
+ errorMsg( "Error exit delayed from previous errors\n");
return( FALSE);
} else
return( status);
close( tarFd);
if ( *(header.name) == '\0' ) {
if (errorFlag==TRUE)
- errorMsg( "tar: Error exit delayed from previous errors\n");
+ errorMsg( "Error exit delayed from previous errors\n");
else
return( TRUE);
}
if (*fileName=='/') {
static int alreadyWarned=FALSE;
if (alreadyWarned==FALSE) {
- errorMsg("tar: Removing leading '/' from member names\n");
+ errorMsg("Removing leading '/' from member names\n");
alreadyWarned=TRUE;
}
strncpy(header.name, fileName+1, sizeof(header.name));
/* WARNING/NOTICE: I break Hard Links */
if (S_ISLNK(statbuf->st_mode)) {
+ int link_size=0;
char buffer[BUFSIZ];
header.typeflag = SYMTYPE;
- if ( readlink(fileName, buffer, sizeof(buffer) - 1) < 0) {
+ link_size = readlink(fileName, buffer, sizeof(buffer) - 1);
+ if ( link_size < 0) {
errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
return ( FALSE);
}
+ buffer[link_size] = '\0';
strncpy(header.linkname, buffer, sizeof(header.linkname));
} else if (S_ISDIR(statbuf->st_mode)) {
header.typeflag = DIRTYPE;
header.typeflag = REGTYPE;
putOctal(header.size, sizeof(header.size), statbuf->st_size);
} else {
- errorMsg("tar: %s: Unknown file type\n", fileName);
+ errorMsg("%s: Unknown file type\n", fileName);
return ( FALSE);
}
/* It is against the rules to archive a socket */
if (S_ISSOCK(statbuf->st_mode)) {
- errorMsg("tar: %s: socket ignored\n", fileName);
+ errorMsg("%s: socket ignored\n", fileName);
return( TRUE);
}
* the new tarball */
if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
tbInfo->statBuf.st_ino == statbuf->st_ino) {
- errorMsg("tar: %s: file is the archive; skipping\n", fileName);
+ errorMsg("%s: file is the archive; skipping\n", fileName);
return( TRUE);
}
/* 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));
+ errorMsg("%s: Cannot open: %s\n", fileName, strerror(errno));
return( FALSE);
}
/* Make sure there is at least one file to tar up. */
if (argc <= 0)
- fatalError("tar: Cowardly refusing to create an empty archive\n");
+ fatalError("Cowardly refusing to create an empty archive\n");
/* Open the tar file for writing. */
if (tostdoutFlag == TRUE)
else
tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (tbInfo.tarFd < 0) {
- errorMsg( "tar: Error opening '%s': %s\n", tarName, strerror(errno));
+ errorMsg( "Error opening '%s': %s\n", tarName, strerror(errno));
return ( FALSE);
}
tbInfo.excludeList=excludeList;
/* Hang up the tools, close up shop, head home */
close(tarFd);
if (errorFlag == TRUE) {
- errorMsg("tar: Error exit delayed from previous errors\n");
+ errorMsg("Error exit delayed from previous errors\n");
return(FALSE);
}
return( TRUE);