- if (close (fd) < 0)
- FATAL_ERROR ((0, errno, _("Cannot close file #%d"), fd));
-}
-
-/*-----------------------------------------------------------------------.
-| Duplicate file descriptor FROM into becoming INTO, or else, issue |
-| MESSAGE. INTO is closed first and has to be the next available slot. |
-`-----------------------------------------------------------------------*/
-
-static void
-xdup2 (int from, int into, const char *message)
-{
- if (from != into)
- {
- int status = close (into);
-
- if (status < 0 && errno != EBADF)
- FATAL_ERROR ((0, errno, _("Cannot close descriptor %d"), into));
- status = dup (from);
- if (status != into)
- FATAL_ERROR ((0, errno, _("Cannot properly duplicate %s"), message));
- xclose (from);
- }
-}
-
-#if MSDOS
-
-/*-------------------------------------------------------.
-| Set ARCHIVE for writing, then compressing an archive. |
-`-------------------------------------------------------*/
-
-static void
-child_open_for_compress (void)
-{
- FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
-}
-
-/*---------------------------------------------------------.
-| Set ARCHIVE for uncompressing, then reading an archive. |
-`---------------------------------------------------------*/
-
-static void
-child_open_for_uncompress (void)
-{
- FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
-}
-
-#else /* not MSDOS */
-
-/*---------------------------------------------------------------------.
-| Return nonzero if NAME is the name of a regular file, or if the file |
-| does not exist (so it would be created as a regular file). |
-`---------------------------------------------------------------------*/
-
-static int
-is_regular_file (const char *name)
-{
- struct stat stbuf;
-
- if (stat (name, &stbuf) < 0)
- return 1;
-
- if (S_ISREG (stbuf.st_mode))
- return 1;
-
- return 0;
-}
-
-/*-------------------------------------------------------.
-| Set ARCHIVE for writing, then compressing an archive. |
-`-------------------------------------------------------*/
-
-static void
-child_open_for_compress (void)
-{
- int parent_pipe[2];
- int child_pipe[2];
- pid_t grandchild_pid;
-
- if (pipe (parent_pipe) < 0)
- FATAL_ERROR ((0, errno, _("Cannot open pipe")));
-
- child_pid = fork ();
- if (child_pid < 0)
- FATAL_ERROR ((0, errno, _("Cannot fork")));
-
- if (child_pid > 0)
- {
- /* The parent tar is still here! Just clean up. */
-
- archive = parent_pipe[PWRITE];
- xclose (parent_pipe[PREAD]);
- return;
- }
-
- /* The new born child tar is here! */
-
- program_name = _("tar (child)");
-
- xdup2 (parent_pipe[PREAD], STDIN, _("(child) Pipe to stdin"));
- 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. */
-
- if (strcmp (archive_name_array[0], "-") != 0
- && !_remdev (archive_name_array[0])
- && is_regular_file (archive_name_array[0]))
- {
- if (backup_option)
- maybe_backup_file (archive_name_array[0], 1);
-
- /* We don't need a grandchild tar. Open the archive and launch the
- compressor. */
-
- archive = creat (archive_name_array[0], 0666);
- if (archive < 0)
- {
- int saved_errno = errno;
-
- if (backup_option)
- undo_last_backup ();
- FATAL_ERROR ((0, saved_errno, _("Cannot open archive %s"),
- archive_name_array[0]));
- }
- xdup2 (archive, STDOUT, _("Archive to stdout"));
- execlp (use_compress_program_option, use_compress_program_option,
- (char *) 0);
- FATAL_ERROR ((0, errno, _("Cannot exec %s"),
- use_compress_program_option));
- }
-
- /* We do need a grandchild tar. */
-
- if (pipe (child_pipe) < 0)
- FATAL_ERROR ((0, errno, _("Cannot open pipe")));
-
- grandchild_pid = fork ();
- if (grandchild_pid < 0)
- FATAL_ERROR ((0, errno, _("Child cannot fork")));
-
- if (grandchild_pid > 0)
- {
- /* The child tar is still here! Launch the compressor. */
-
- xdup2 (child_pipe[PWRITE], STDOUT, _("((child)) Pipe to stdout"));
- xclose (child_pipe[PREAD]);
- execlp (use_compress_program_option, use_compress_program_option,
- (char *) 0);
- FATAL_ERROR ((0, errno, _("Cannot exec %s"),
- use_compress_program_option));
- }
-
- /* The new born grandchild tar is here! */
-
- program_name = _("tar (grandchild)");
-
- /* Prepare for reblocking the data from the compressor into the archive. */
-
- xdup2 (child_pipe[PREAD], STDIN, _("(grandchild) Pipe to stdin"));
- xclose (child_pipe[PWRITE]);
-
- if (strcmp (archive_name_array[0], "-") == 0)
- archive = STDOUT;
- else
- archive = rmtcreat (archive_name_array[0], 0666, rsh_command_option);
- if (archive < 0)
- FATAL_ERROR ((0, errno, _("Cannot open archive %s"),
- archive_name_array[0]));
-
- /* Let's read out of the stdin pipe and write an archive. */
-
- while (1)
- {
- ssize_t status = 0;
- char *cursor;
- size_t length;
-
- /* Assemble a record. */
-
- for (length = 0, cursor = record_start->buffer;
- length < record_size;
- length += status, cursor += status)
- {
- size_t size = record_size - length;
-
- if (size < BLOCKSIZE)
- size = BLOCKSIZE;
- status = read (STDIN, cursor, size);
- if (status <= 0)
- break;
- }
-
- if (status < 0)
- FATAL_ERROR ((0, errno, _("Cannot read from compression program")));
-
- /* Copy the record. */
-
- if (status == 0)
- {
- /* We hit the end of the file. Write last record at
- full length, as the only role of the grandchild is
- doing proper reblocking. */
-
- if (length > 0)
- {
- memset (record_start->buffer + length, 0, record_size - length);
- status = rmtwrite (archive, record_start->buffer, record_size);
- if (status != record_size)
- write_error (status);
- }
-
- /* There is nothing else to read, break out. */
- break;
- }
-
- status = rmtwrite (archive, record_start->buffer, record_size);
- if (status != record_size)
- write_error (status);
- }
-
-#if 0
- close_archive ();
-#endif
- exit (exit_status);
-}
-
-/*---------------------------------------------------------.
-| Set ARCHIVE for uncompressing, then reading an archive. |
-`---------------------------------------------------------*/
-
-static void
-child_open_for_uncompress (void)
-{
- int parent_pipe[2];
- int child_pipe[2];
- pid_t grandchild_pid;
-
- if (pipe (parent_pipe) < 0)
- FATAL_ERROR ((0, errno, _("Cannot open pipe")));
-
- child_pid = fork ();
- if (child_pid < 0)
- FATAL_ERROR ((0, errno, _("Cannot fork")));
-
- if (child_pid > 0)
- {
- /* The parent tar is still here! Just clean up. */
-
- read_full_records_option = 1;
- archive = parent_pipe[PREAD];
- xclose (parent_pipe[PWRITE]);
- return;
- }
-
- /* The new born child tar is here! */
-
- program_name = _("tar (child)");
-
- xdup2 (parent_pipe[PWRITE], STDOUT, _("(child) Pipe to stdout"));
- xclose (parent_pipe[PREAD]);
-
- /* Check if we need a grandchild tar. This happens only if either:
- a) we're reading stdin: to force unblocking;
- b) the file is to be accessed by rmt: compressor doesn't know how;
- c) the file is not a plain file. */
-
- if (strcmp (archive_name_array[0], "-") != 0
- && !_remdev (archive_name_array[0])
- && is_regular_file (archive_name_array[0]))
- {
- /* We don't need a grandchild tar. Open the archive and lauch the
- uncompressor. */
-
- archive = open (archive_name_array[0], O_RDONLY | O_BINARY, 0666);
- if (archive < 0)
- FATAL_ERROR ((0, errno, _("Cannot open archive %s"),
- archive_name_array[0]));
- xdup2 (archive, STDIN, _("Archive to stdin"));
- execlp (use_compress_program_option, use_compress_program_option,
- "-d", (char *) 0);
- FATAL_ERROR ((0, errno, _("Cannot exec %s"),
- use_compress_program_option));
- }
-
- /* We do need a grandchild tar. */
-
- if (pipe (child_pipe) < 0)
- FATAL_ERROR ((0, errno, _("Cannot open pipe")));
-
- grandchild_pid = fork ();
- if (grandchild_pid < 0)
- FATAL_ERROR ((0, errno, _("Child cannot fork")));
-
- if (grandchild_pid > 0)
- {
- /* The child tar is still here! Launch the uncompressor. */
-
- xdup2 (child_pipe[PREAD], STDIN, _("((child)) Pipe to stdin"));
- xclose (child_pipe[PWRITE]);
- execlp (use_compress_program_option, use_compress_program_option,
- "-d", (char *) 0);
- FATAL_ERROR ((0, errno, _("Cannot exec %s"),
- use_compress_program_option));
- }
-
- /* The new born grandchild tar is here! */
-
- program_name = _("tar (grandchild)");
-
- /* Prepare for unblocking the data from the archive into the uncompressor. */
-
- xdup2 (child_pipe[PWRITE], STDOUT, _("(grandchild) Pipe to stdout"));
- xclose (child_pipe[PREAD]);
-
- if (strcmp (archive_name_array[0], "-") == 0)
- archive = STDIN;
- else
- archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
- 0666, rsh_command_option);
- if (archive < 0)
- FATAL_ERROR ((0, errno, _("Cannot open archive %s"),
- archive_name_array[0]));
-
- /* Let's read the archive and pipe it into stdout. */
-
- while (1)
- {
- char *cursor;
- size_t maximum;
- size_t count;
- ssize_t status;
-
- read_error_count = 0;
-
- error_loop:
- status = rmtread (archive, record_start->buffer, record_size);
- if (status < 0)
- {
- read_error ();
- goto error_loop;
- }
- if (status == 0)
- break;
- cursor = record_start->buffer;
- maximum = status;
- while (maximum)
- {
- count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE;
- status = write (STDOUT, cursor, count);
- if (status < 0)
- FATAL_ERROR ((0, errno, _("\
-Cannot write to compression program")));
-
- if (status != count)
- {
- ERROR ((0, 0, _("\
-Write to compression program short %lu bytes"),
- (unsigned long) (count - status)));
- count = status;
- }
-
- cursor += count;
- maximum -= count;
- }
- }
-
-#if 0
- close_archive ();
-#endif
- exit (exit_status);