mirror of
https://github.com/sheumann/hush.git
synced 2024-09-12 00:55:11 +00:00
tar: move vfork into separate function (smaller code)
open_transformer: more informative error messages function old new delta vfork_compressor - 210 +210 writeTarFile 547 299 -248 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 210/-248) Total: -38 bytes
This commit is contained in:
parent
a4a93fdf18
commit
5a07a1d255
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Busybox version: 1.10.0.svn
|
# Busybox version: 1.11.0.svn
|
||||||
# Thu Mar 20 14:54:21 2008
|
# Mon Apr 21 23:20:35 2008
|
||||||
#
|
#
|
||||||
CONFIG_HAVE_DOT_CONFIG=y
|
CONFIG_HAVE_DOT_CONFIG=y
|
||||||
|
|
||||||
@ -100,6 +100,7 @@ CONFIG_FEATURE_AR_LONG_FILENAMES=y
|
|||||||
CONFIG_BUNZIP2=y
|
CONFIG_BUNZIP2=y
|
||||||
CONFIG_BZIP2=y
|
CONFIG_BZIP2=y
|
||||||
CONFIG_CPIO=y
|
CONFIG_CPIO=y
|
||||||
|
CONFIG_FEATURE_CPIO_O=y
|
||||||
CONFIG_DPKG=y
|
CONFIG_DPKG=y
|
||||||
CONFIG_DPKG_DEB=y
|
CONFIG_DPKG_DEB=y
|
||||||
CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY=y
|
CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY=y
|
||||||
@ -485,6 +486,7 @@ CONFIG_LOSETUP=y
|
|||||||
CONFIG_MDEV=y
|
CONFIG_MDEV=y
|
||||||
CONFIG_FEATURE_MDEV_CONF=y
|
CONFIG_FEATURE_MDEV_CONF=y
|
||||||
CONFIG_FEATURE_MDEV_RENAME=y
|
CONFIG_FEATURE_MDEV_RENAME=y
|
||||||
|
CONFIG_FEATURE_MDEV_RENAME_REGEXP=y
|
||||||
CONFIG_FEATURE_MDEV_EXEC=y
|
CONFIG_FEATURE_MDEV_EXEC=y
|
||||||
CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y
|
CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y
|
||||||
CONFIG_MKSWAP=y
|
CONFIG_MKSWAP=y
|
||||||
@ -521,6 +523,7 @@ CONFIG_PIVOT_ROOT=y
|
|||||||
CONFIG_RDATE=y
|
CONFIG_RDATE=y
|
||||||
CONFIG_READPROFILE=y
|
CONFIG_READPROFILE=y
|
||||||
CONFIG_RTCWAKE=y
|
CONFIG_RTCWAKE=y
|
||||||
|
CONFIG_SCRIPT=y
|
||||||
CONFIG_SETARCH=y
|
CONFIG_SETARCH=y
|
||||||
CONFIG_SWAPONOFF=y
|
CONFIG_SWAPONOFF=y
|
||||||
CONFIG_SWITCH_ROOT=y
|
CONFIG_SWITCH_ROOT=y
|
||||||
@ -559,6 +562,7 @@ CONFIG_DC=y
|
|||||||
# CONFIG_FEATURE_DEVFS is not set
|
# CONFIG_FEATURE_DEVFS is not set
|
||||||
CONFIG_EJECT=y
|
CONFIG_EJECT=y
|
||||||
CONFIG_FEATURE_EJECT_SCSI=y
|
CONFIG_FEATURE_EJECT_SCSI=y
|
||||||
|
CONFIG_FBSPLASH=y
|
||||||
CONFIG_LAST=y
|
CONFIG_LAST=y
|
||||||
CONFIG_LESS=y
|
CONFIG_LESS=y
|
||||||
CONFIG_FEATURE_LESS_MAXLINES=9999999
|
CONFIG_FEATURE_LESS_MAXLINES=9999999
|
||||||
@ -577,6 +581,7 @@ CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA=y
|
|||||||
CONFIG_MAKEDEVS=y
|
CONFIG_MAKEDEVS=y
|
||||||
# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
|
# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
|
||||||
CONFIG_FEATURE_MAKEDEVS_TABLE=y
|
CONFIG_FEATURE_MAKEDEVS_TABLE=y
|
||||||
|
CONFIG_MAN=y
|
||||||
CONFIG_MICROCOM=y
|
CONFIG_MICROCOM=y
|
||||||
CONFIG_MOUNTPOINT=y
|
CONFIG_MOUNTPOINT=y
|
||||||
CONFIG_MT=y
|
CONFIG_MT=y
|
||||||
@ -584,9 +589,9 @@ CONFIG_RAIDAUTORUN=y
|
|||||||
CONFIG_READAHEAD=y
|
CONFIG_READAHEAD=y
|
||||||
CONFIG_RUNLEVEL=y
|
CONFIG_RUNLEVEL=y
|
||||||
CONFIG_RX=y
|
CONFIG_RX=y
|
||||||
CONFIG_SCRIPT=y
|
|
||||||
CONFIG_STRINGS=y
|
|
||||||
CONFIG_SETSID=y
|
CONFIG_SETSID=y
|
||||||
|
CONFIG_STRINGS=y
|
||||||
|
CONFIG_SYMLINKS=y
|
||||||
CONFIG_TASKSET=y
|
CONFIG_TASKSET=y
|
||||||
CONFIG_FEATURE_TASKSET_FANCY=y
|
CONFIG_FEATURE_TASKSET_FANCY=y
|
||||||
CONFIG_TIME=y
|
CONFIG_TIME=y
|
||||||
@ -603,6 +608,7 @@ CONFIG_ARP=y
|
|||||||
CONFIG_ARPING=y
|
CONFIG_ARPING=y
|
||||||
CONFIG_BRCTL=y
|
CONFIG_BRCTL=y
|
||||||
CONFIG_FEATURE_BRCTL_FANCY=y
|
CONFIG_FEATURE_BRCTL_FANCY=y
|
||||||
|
CONFIG_FEATURE_BRCTL_SHOW=y
|
||||||
CONFIG_DNSD=y
|
CONFIG_DNSD=y
|
||||||
CONFIG_ETHER_WAKE=y
|
CONFIG_ETHER_WAKE=y
|
||||||
CONFIG_FAKEIDENTD=y
|
CONFIG_FAKEIDENTD=y
|
||||||
@ -751,6 +757,7 @@ CONFIG_WATCH=y
|
|||||||
# CONFIG_FEATURE_SH_IS_MSH is not set
|
# CONFIG_FEATURE_SH_IS_MSH is not set
|
||||||
CONFIG_FEATURE_SH_IS_NONE=y
|
CONFIG_FEATURE_SH_IS_NONE=y
|
||||||
# CONFIG_ASH is not set
|
# CONFIG_ASH is not set
|
||||||
|
# CONFIG_ASH_BASH_COMPAT is not set
|
||||||
# CONFIG_ASH_JOB_CONTROL is not set
|
# CONFIG_ASH_JOB_CONTROL is not set
|
||||||
# CONFIG_ASH_READ_NCHARS is not set
|
# CONFIG_ASH_READ_NCHARS is not set
|
||||||
# CONFIG_ASH_READ_TIMEOUT is not set
|
# CONFIG_ASH_READ_TIMEOUT is not set
|
||||||
@ -780,6 +787,7 @@ CONFIG_MSH=y
|
|||||||
#
|
#
|
||||||
CONFIG_FEATURE_SH_EXTRA_QUIET=y
|
CONFIG_FEATURE_SH_EXTRA_QUIET=y
|
||||||
CONFIG_FEATURE_SH_STANDALONE=y
|
CONFIG_FEATURE_SH_STANDALONE=y
|
||||||
|
CONFIG_FEATURE_SH_NOFORK=y
|
||||||
CONFIG_CTTYHACK=y
|
CONFIG_CTTYHACK=y
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -22,11 +22,13 @@ int open_transformer(int src_fd,
|
|||||||
|
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
if (pid == -1)
|
||||||
|
bb_perror_msg_and_die("can't fork");
|
||||||
#else
|
#else
|
||||||
pid = vfork();
|
pid = vfork();
|
||||||
#endif
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
bb_perror_msg_and_die("fork failed");
|
bb_perror_msg_and_die("can't vfork");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
/* child process */
|
/* child process */
|
||||||
@ -49,7 +51,7 @@ int open_transformer(int src_fd,
|
|||||||
argv[2] = (char*)"-";
|
argv[2] = (char*)"-";
|
||||||
argv[3] = NULL;
|
argv[3] = NULL;
|
||||||
BB_EXECVP(transform_prog, argv);
|
BB_EXECVP(transform_prog, argv);
|
||||||
bb_perror_msg_and_die("exec failed");
|
bb_perror_msg_and_die("can't exec %s", transform_prog);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* notreached */
|
/* notreached */
|
||||||
|
202
archival/tar.c
202
archival/tar.c
@ -84,26 +84,26 @@ struct TarHeader { /* byte offset */
|
|||||||
*/
|
*/
|
||||||
typedef struct HardLinkInfo HardLinkInfo;
|
typedef struct HardLinkInfo HardLinkInfo;
|
||||||
struct HardLinkInfo {
|
struct HardLinkInfo {
|
||||||
HardLinkInfo *next; /* Next entry in list */
|
HardLinkInfo *next; /* Next entry in list */
|
||||||
dev_t dev; /* Device number */
|
dev_t dev; /* Device number */
|
||||||
ino_t ino; /* Inode number */
|
ino_t ino; /* Inode number */
|
||||||
short linkCount; /* (Hard) Link Count */
|
short linkCount; /* (Hard) Link Count */
|
||||||
char name[1]; /* Start of filename (must be last) */
|
char name[1]; /* Start of filename (must be last) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Some info to be carried along when creating a new tarball */
|
/* Some info to be carried along when creating a new tarball */
|
||||||
typedef struct TarBallInfo TarBallInfo;
|
typedef struct TarBallInfo TarBallInfo;
|
||||||
struct TarBallInfo {
|
struct TarBallInfo {
|
||||||
int tarFd; /* Open-for-write file descriptor
|
int tarFd; /* Open-for-write file descriptor
|
||||||
for the tarball */
|
* for the tarball */
|
||||||
struct stat statBuf; /* Stat info for the tarball, letting
|
struct stat statBuf; /* Stat info for the tarball, letting
|
||||||
us know the inode and device that the
|
* us know the inode and device that the
|
||||||
tarball lives, so we can avoid trying
|
* tarball lives, so we can avoid trying
|
||||||
to include the tarball into itself */
|
* to include the tarball into itself */
|
||||||
int verboseFlag; /* Whether to print extra stuff or not */
|
int verboseFlag; /* Whether to print extra stuff or not */
|
||||||
const llist_t *excludeList; /* List of files to not include */
|
const llist_t *excludeList; /* List of files to not include */
|
||||||
HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
|
HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
|
||||||
HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
|
HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A nice enum with all the possible tar file content types */
|
/* A nice enum with all the possible tar file content types */
|
||||||
@ -503,11 +503,87 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeTarFile(const int tar_fd, const int verboseFlag,
|
#if ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2
|
||||||
const unsigned long dereferenceFlag, const llist_t *include,
|
/* Don't inline: vfork scares gcc and pessimizes code */
|
||||||
const llist_t *exclude, const int gzip)
|
static void NOINLINE vfork_compressor(int tar_fd, int gzip)
|
||||||
|
{
|
||||||
|
pid_t gzipPid;
|
||||||
|
#if ENABLE_FEATURE_TAR_GZIP && ENABLE_FEATURE_TAR_BZIP2
|
||||||
|
const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
|
||||||
|
#elif ENABLE_FEATURE_TAR_GZIP
|
||||||
|
const char *zip_exec = "gzip";
|
||||||
|
#else /* only ENABLE_FEATURE_TAR_BZIP2 */
|
||||||
|
const char *zip_exec = "bzip2";
|
||||||
|
#endif
|
||||||
|
// On Linux, vfork never unpauses parent early, although standard
|
||||||
|
// allows for that. Do we want to waste bytes checking for it?
|
||||||
|
#define WAIT_FOR_CHILD 0
|
||||||
|
volatile int vfork_exec_errno = 0;
|
||||||
|
struct fd_pair gzipDataPipe;
|
||||||
|
#if WAIT_FOR_CHILD
|
||||||
|
struct fd_pair gzipStatusPipe;
|
||||||
|
xpiped_pair(gzipStatusPipe);
|
||||||
|
#endif
|
||||||
|
xpiped_pair(gzipDataPipe);
|
||||||
|
|
||||||
|
signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && __GNUC__
|
||||||
|
/* Avoid vfork clobbering */
|
||||||
|
(void) &zip_exec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gzipPid = vfork();
|
||||||
|
if (gzipPid < 0)
|
||||||
|
bb_perror_msg_and_die("can't vfork");
|
||||||
|
|
||||||
|
if (gzipPid == 0) {
|
||||||
|
/* child */
|
||||||
|
/* NB: close _first_, then move fds! */
|
||||||
|
close(gzipDataPipe.wr);
|
||||||
|
#if WAIT_FOR_CHILD
|
||||||
|
close(gzipStatusPipe.rd);
|
||||||
|
/* gzipStatusPipe.wr will close only on exec -
|
||||||
|
* parent waits for this close to happen */
|
||||||
|
fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
xmove_fd(gzipDataPipe.rd, 0);
|
||||||
|
xmove_fd(tar_fd, 1);
|
||||||
|
/* exec gzip/bzip2 program/applet */
|
||||||
|
BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
|
||||||
|
vfork_exec_errno = errno;
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parent */
|
||||||
|
xmove_fd(gzipDataPipe.wr, tar_fd);
|
||||||
|
close(gzipDataPipe.rd);
|
||||||
|
#if WAIT_FOR_CHILD
|
||||||
|
close(gzipStatusPipe.wr);
|
||||||
|
while (1) {
|
||||||
|
char buf;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* Wait until child execs (or fails to) */
|
||||||
|
n = full_read(gzipStatusPipe.rd, &buf, 1);
|
||||||
|
if (n < 0 /* && errno == EAGAIN */)
|
||||||
|
continue; /* try it again */
|
||||||
|
}
|
||||||
|
close(gzipStatusPipe.rd);
|
||||||
|
#endif
|
||||||
|
if (vfork_exec_errno) {
|
||||||
|
errno = vfork_exec_errno;
|
||||||
|
bb_perror_msg_and_die("cannot exec %s", zip_exec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2 */
|
||||||
|
|
||||||
|
|
||||||
|
/* gcc 4.2.1 inlines it, making code bigger */
|
||||||
|
static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
|
||||||
|
int dereferenceFlag, const llist_t *include,
|
||||||
|
const llist_t *exclude, int gzip)
|
||||||
{
|
{
|
||||||
pid_t gzipPid = 0;
|
|
||||||
int errorFlag = FALSE;
|
int errorFlag = FALSE;
|
||||||
struct TarBallInfo tbInfo;
|
struct TarBallInfo tbInfo;
|
||||||
|
|
||||||
@ -523,80 +599,8 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
|
|||||||
bb_perror_msg_and_die("cannot stat tar file");
|
bb_perror_msg_and_die("cannot stat tar file");
|
||||||
|
|
||||||
#if ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2
|
#if ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2
|
||||||
if (gzip) {
|
if (gzip)
|
||||||
#if ENABLE_FEATURE_TAR_GZIP && ENABLE_FEATURE_TAR_BZIP2
|
vfork_compressor(tbInfo.tarFd, gzip);
|
||||||
const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
|
|
||||||
#elif ENABLE_FEATURE_TAR_GZIP
|
|
||||||
const char *zip_exec = "gzip";
|
|
||||||
#else /* only ENABLE_FEATURE_TAR_BZIP2 */
|
|
||||||
const char *zip_exec = "bzip2";
|
|
||||||
#endif
|
|
||||||
// On Linux, vfork never unpauses parent early, although standard
|
|
||||||
// allows for that. Do we want to waste bytes checking for it?
|
|
||||||
#define WAIT_FOR_CHILD 0
|
|
||||||
volatile int vfork_exec_errno = 0;
|
|
||||||
#if WAIT_FOR_CHILD
|
|
||||||
struct fd_pair gzipStatusPipe;
|
|
||||||
#endif
|
|
||||||
struct fd_pair gzipDataPipe;
|
|
||||||
xpiped_pair(gzipDataPipe);
|
|
||||||
#if WAIT_FOR_CHILD
|
|
||||||
xpiped_pair(gzipStatusPipe);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && __GNUC__
|
|
||||||
/* Avoid vfork clobbering */
|
|
||||||
(void) &include;
|
|
||||||
(void) &errorFlag;
|
|
||||||
(void) &zip_exec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gzipPid = vfork();
|
|
||||||
if (gzipPid < 0)
|
|
||||||
bb_perror_msg_and_die("vfork gzip");
|
|
||||||
|
|
||||||
if (gzipPid == 0) {
|
|
||||||
/* child */
|
|
||||||
/* NB: close _first_, then move fds! */
|
|
||||||
close(gzipDataPipe.wr);
|
|
||||||
#if WAIT_FOR_CHILD
|
|
||||||
close(gzipStatusPipe.rd);
|
|
||||||
/* gzipStatusPipe.wr will close only on exec -
|
|
||||||
* parent waits for this close to happen */
|
|
||||||
fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
|
|
||||||
#endif
|
|
||||||
xmove_fd(gzipDataPipe.rd, 0);
|
|
||||||
xmove_fd(tbInfo.tarFd, 1);
|
|
||||||
/* exec gzip/bzip2 program/applet */
|
|
||||||
BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
|
|
||||||
vfork_exec_errno = errno;
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parent */
|
|
||||||
xmove_fd(gzipDataPipe.wr, tbInfo.tarFd);
|
|
||||||
close(gzipDataPipe.rd);
|
|
||||||
#if WAIT_FOR_CHILD
|
|
||||||
close(gzipStatusPipe.wr);
|
|
||||||
while (1) {
|
|
||||||
char buf;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
/* Wait until child execs (or fails to) */
|
|
||||||
n = full_read(gzipStatusPipe.rd, &buf, 1);
|
|
||||||
if (n < 0 /* && errno == EAGAIN */)
|
|
||||||
continue; /* try it again */
|
|
||||||
|
|
||||||
}
|
|
||||||
close(gzipStatusPipe.rd);
|
|
||||||
#endif
|
|
||||||
if (vfork_exec_errno) {
|
|
||||||
errno = vfork_exec_errno;
|
|
||||||
bb_perror_msg_and_die("cannot exec %s", zip_exec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tbInfo.excludeList = exclude;
|
tbInfo.excludeList = exclude;
|
||||||
@ -630,20 +634,22 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
|
|||||||
if (errorFlag)
|
if (errorFlag)
|
||||||
bb_error_msg("error exit delayed from previous errors");
|
bb_error_msg("error exit delayed from previous errors");
|
||||||
|
|
||||||
if (gzipPid) {
|
#if ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2
|
||||||
|
if (gzip) {
|
||||||
int status;
|
int status;
|
||||||
if (safe_waitpid(gzipPid, &status, 0) == -1)
|
if (safe_waitpid(-1, &status, 0) == -1)
|
||||||
bb_perror_msg("waitpid");
|
bb_perror_msg("waitpid");
|
||||||
else if (!WIFEXITED(status) || WEXITSTATUS(status))
|
else if (!WIFEXITED(status) || WEXITSTATUS(status))
|
||||||
/* gzip was killed or has exited with nonzero! */
|
/* gzip was killed or has exited with nonzero! */
|
||||||
errorFlag = TRUE;
|
errorFlag = TRUE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return errorFlag;
|
return errorFlag;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int writeTarFile(const int tar_fd, const int verboseFlag,
|
int writeTarFile(int tar_fd, int verboseFlag,
|
||||||
const unsigned long dereferenceFlag, const llist_t *include,
|
int dereferenceFlag, const llist_t *include,
|
||||||
const llist_t *exclude, const int gzip);
|
const llist_t *exclude, int gzip);
|
||||||
#endif /* FEATURE_TAR_CREATE */
|
#endif /* FEATURE_TAR_CREATE */
|
||||||
|
|
||||||
#if ENABLE_FEATURE_TAR_FROM
|
#if ENABLE_FEATURE_TAR_FROM
|
||||||
|
Loading…
Reference in New Issue
Block a user