/* 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
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
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);
}
}
-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 */