/* System-dependent calls for tar.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any later
+ Free Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <system.h>
+#include <setenv.h>
#include "common.h"
#include <rmt.h>
if (archive < 0)
{
int saved_errno = errno;
-
+
if (backup_option)
undo_last_backup ();
errno = saved_errno;
static void
stat_to_env (char *name, char type, struct tar_stat_info *st)
{
+ str_to_env ("TAR_VERSION", PACKAGE_VERSION);
chr_to_env ("TAR_FILETYPE", type);
oct_to_env ("TAR_MODE", st->stat.st_mode);
str_to_env ("TAR_FILENAME", name);
}
}
-static pid_t pid;
+static pid_t global_pid;
static RETSIGTYPE (*pipe_handler) (int sig);
int
xpipe (p);
pipe_handler = signal (SIGPIPE, SIG_IGN);
- pid = xfork ();
+ global_pid = xfork ();
- if (pid != 0)
+ if (global_pid != 0)
{
xclose (p[PREAD]);
return p[PWRITE];
{
int status;
- if (pid < 0)
+ if (global_pid < 0)
return;
signal (SIGPIPE, pipe_handler);
- while (waitpid (pid, &status, 0) == -1)
+ while (waitpid (global_pid, &status, 0) == -1)
if (errno != EINTR)
{
- pid = -1;
+ global_pid = -1;
waitpid_error (to_command_option);
return;
}
{
if (!ignore_command_error_option && WEXITSTATUS (status))
ERROR ((0, 0, _("%lu: Child returned status %d"),
- (unsigned long) pid, WEXITSTATUS (status)));
+ (unsigned long) global_pid, WEXITSTATUS (status)));
}
else if (WIFSIGNALED (status))
{
WARN ((0, 0, _("%lu: Child terminated on signal %d"),
- (unsigned long) pid, WTERMSIG (status)));
+ (unsigned long) global_pid, WTERMSIG (status)));
}
else
ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
- (unsigned long) pid));
+ (unsigned long) global_pid));
+
+ global_pid = -1;
+}
+
+int
+sys_exec_info_script (const char **archive_name, int volume_number)
+{
+ pid_t pid;
+ char *argv[4];
+ char uintbuf[UINTMAX_STRSIZE_BOUND];
+ int p[2];
+ static RETSIGTYPE (*saved_handler) (int sig);
+
+ xpipe (p);
+ saved_handler = signal (SIGPIPE, SIG_IGN);
+
+ pid = xfork ();
+
+ if (pid != 0)
+ {
+ /* Master */
+
+ int rc;
+ int status;
+ char *buf = NULL;
+ size_t size = 0;
+ FILE *fp;
+
+ xclose (p[PWRITE]);
+ fp = fdopen (p[PREAD], "r");
+ rc = getline (&buf, &size, fp);
+ fclose (fp);
+
+ if (rc > 0 && buf[rc-1] == '\n')
+ buf[--rc] = 0;
+
+ while (waitpid (pid, &status, 0) == -1)
+ if (errno != EINTR)
+ {
+ signal (SIGPIPE, saved_handler);
+ waitpid_error (info_script_option);
+ return -1;
+ }
+
+ signal (SIGPIPE, saved_handler);
+
+ if (WIFEXITED (status))
+ {
+ if (WEXITSTATUS (status) == 0 && rc > 0)
+ *archive_name = buf;
+ else
+ free (buf);
+ return WEXITSTATUS (status);
+ }
+
+ free (buf);
+ return -1;
+ }
+
+ /* Child */
+ setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
+ setenv ("TAR_ARCHIVE", *archive_name, 1);
+ setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
+ setenv ("TAR_BLOCKING_FACTOR",
+ STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
+ setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
+ setenv ("TAR_FORMAT",
+ archive_format_string (current_format == DEFAULT_FORMAT ?
+ archive_format : current_format), 1);
+ setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
+
+ xclose (p[PREAD]);
+
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+ argv[2] = (char*) info_script_option;
+ argv[3] = NULL;
+
+ execv (argv[0], argv);
+
+ exec_fatal (info_script_option);
+}
+
+void
+sys_exec_checkpoint_script (const char *script_name,
+ const char *archive_name,
+ int checkpoint_number)
+{
+ pid_t pid;
+ char *argv[4];
+ char uintbuf[UINTMAX_STRSIZE_BOUND];
+
+ pid = xfork ();
+
+ if (pid != 0)
+ {
+ /* Master */
+
+ int status;
+
+ while (waitpid (pid, &status, 0) == -1)
+ if (errno != EINTR)
+ {
+ waitpid_error (script_name);
+ break;
+ }
+
+ return;
+ }
+
+ /* Child */
+ setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
+ setenv ("TAR_ARCHIVE", archive_name, 1);
+ setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1);
+ setenv ("TAR_BLOCKING_FACTOR",
+ STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
+ setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
+ setenv ("TAR_FORMAT",
+ archive_format_string (current_format == DEFAULT_FORMAT ?
+ archive_format : current_format), 1);
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+ argv[2] = (char*) script_name;
+ argv[3] = NULL;
+
+ execv (argv[0], argv);
- pid = -1;
+ exec_fatal (script_name);
}
#endif /* not MSDOS */