/* 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>
#include <signal.h>
-void
-sys_stat_nanoseconds (struct tar_stat_info *st)
-{
-#if defined(HAVE_STRUCT_STAT_ST_SPARE1)
- st->atime_nsec = st->stat.st_spare1 * 1000;
- st->mtime_nsec = st->stat.st_spare2 * 1000;
- st->ctime_nsec = st->stat.st_spare3 * 1000;
-#elif defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
- st->atime_nsec = st->stat.st_atim.tv_nsec;
- st->mtime_nsec = st->stat.st_mtim.tv_nsec;
- st->ctime_nsec = st->stat.st_ctim.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
- st->atime_nsec = st->stat.st_atimespec.tv_nsec;
- st->mtime_nsec = st->stat.st_mtimespec.tv_nsec;
- st->ctime_nsec = st->stat.st_ctimespec.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
- st->atime_nsec = st->stat.st_atimensec;
- st->mtime_nsec = st->stat.st_mtimensec;
- st->ctime_nsec = st->stat.st_ctimensec;
-#else
- st->atime_nsec = st->mtime_nsec = st->ctime_nsec = 0;
-#endif
-}
-
#if MSDOS
bool
xclose (parent_pipe[PWRITE]);
/* Check if we need a grandchild tar. This happens only if either:
- a) we are writing stdout: to force reblocking;
- b) the file is to be accessed by rmt: compressor doesn't know how;
- c) the file is not a plain file. */
+ a) the file is to be accessed by rmt: compressor doesn't know how;
+ b) the file is not a plain file. */
- if (strcmp (archive_name_array[0], "-") != 0
- && !_remdev (archive_name_array[0])
+ if (!_remdev (archive_name_array[0])
&& is_regular_file (archive_name_array[0]))
{
if (backup_option)
/* We don't need a grandchild tar. Open the archive and launch the
compressor. */
-
- archive = creat (archive_name_array[0], MODE_RW);
- if (archive < 0)
+ if (strcmp (archive_name_array[0], "-"))
{
- int saved_errno = errno;
+ archive = creat (archive_name_array[0], MODE_RW);
+ if (archive < 0)
+ {
+ int saved_errno = errno;
- if (backup_option)
- undo_last_backup ();
- errno = saved_errno;
- open_fatal (archive_name_array[0]);
+ if (backup_option)
+ undo_last_backup ();
+ errno = saved_errno;
+ open_fatal (archive_name_array[0]);
+ }
+ xdup2 (archive, STDOUT_FILENO);
}
- xdup2 (archive, STDOUT_FILENO);
- execlp (use_compress_program_option, use_compress_program_option,
- (char *) 0);
+ execlp (use_compress_program_option, use_compress_program_option, NULL);
exec_fatal (use_compress_program_option);
}
char *numstr;
numstr = STRINGIFY_BIGINT (num, buf);
- setenv (envar, numstr, 1);
+ if (setenv (envar, numstr, 1) != 0)
+ xalloc_die ();
+}
+
+static void
+time_to_env (char *envar, struct timespec t)
+{
+ char buf[TIMESPEC_STRSIZE_BOUND];
+ if (setenv (envar, code_timespec (t, buf), 1) != 0)
+ xalloc_die ();
}
static void
oct_to_env (char *envar, unsigned long num)
{
char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
-
+
snprintf (buf, sizeof buf, "0%lo", num);
- setenv (envar, buf, 1);
+ if (setenv (envar, buf, 1) != 0)
+ xalloc_die ();
}
static void
str_to_env (char *envar, char const *str)
{
if (str)
- setenv (envar, str, 1);
+ {
+ if (setenv (envar, str, 1) != 0)
+ xalloc_die ();
+ }
else
unsetenv (envar);
}
char buf[2];
buf[0] = c;
buf[1] = 0;
- setenv (envar, buf, 1);
+ if (setenv (envar, buf, 1) != 0)
+ xalloc_die ();
}
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);
str_to_env ("TAR_REALNAME", st->file_name);
str_to_env ("TAR_UNAME", st->uname);
str_to_env ("TAR_GNAME", st->gname);
- dec_to_env ("TAR_MTIME", st->stat.st_mtime);
- dec_to_env ("TAR_ATIME", st->stat.st_atime);
- dec_to_env ("TAR_CTIME", st->stat.st_ctime);
+ time_to_env ("TAR_ATIME", st->atime);
+ time_to_env ("TAR_MTIME", st->mtime);
+ time_to_env ("TAR_CTIME", st->ctime);
dec_to_env ("TAR_SIZE", st->stat.st_size);
dec_to_env ("TAR_UID", st->stat.st_uid);
- dec_to_env ("TAR_GID", st->stat.st_gid);
+ dec_to_env ("TAR_GID", st->stat.st_gid);
switch (type)
{
}
}
-static pid_t pid;
+static pid_t global_pid;
static RETSIGTYPE (*pipe_handler) (int sig);
int
{
int p[2];
char *argv[4];
-
+
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];
/* Child */
xdup2 (p[PREAD], STDIN_FILENO);
xclose (p[PWRITE]);
-
+
stat_to_env (file_name, typechar, st);
argv[0] = "/bin/sh";
sys_wait_command (void)
{
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));
- pid = -1;
+ global_pid = -1;
}
-#endif /* not MSDOS */
+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);
+
+ exec_fatal (script_name);
+}
+
+#endif /* not MSDOS */