1 /* System-dependent calls for tar.
3 Copyright (C) 2003 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any later
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 sys_get_archive_stat ()
34 sys_file_is_archive (struct tar_stat_info
*p
)
40 sys_save_archive_dev_ino ()
45 sys_detect_dev_null_output ()
47 static char const dev_null
[] = "nul";
49 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
50 || (! _isrmt (archive
)));
54 sys_drain_input_pipe ()
59 sys_wait_for_child (pid_t child_pid
)
66 spawnl (P_WAIT
, getenv ("COMSPEC"), "-", 0);
69 /* stat() in djgpp's C library gives a constant number of 42 as the
70 uid and gid of a file. So, comparing an FTP'ed archive just after
71 unpack would fail on MSDOS. */
74 sys_compare_uid (struct stat
*a
, struct stat
*b
)
80 sys_compare_gid (struct stat
*a
, struct stat
*b
)
86 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
94 return write (fd
, "", 0);
103 sys_write_archive_buffer (void)
108 while (0 <= (status
= full_write (archive
, record_start
->buffer
+ written
,
109 record_size
- written
)))
112 if (written
== record_size
)
116 return written
? written
: status
;
119 /* Set ARCHIVE for writing, then compressing an archive. */
121 sys_child_open_for_compress (void)
123 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
126 /* Set ARCHIVE for uncompressing, then reading an archive. */
128 sys_child_open_for_uncompress (void)
130 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
135 extern union block
*record_start
; /* FIXME */
137 static struct stat archive_stat
; /* stat block for archive file */
140 sys_get_archive_stat ()
142 return fstat (archive
, &archive_stat
) == 0;
146 sys_file_is_archive (struct tar_stat_info
*p
)
148 return (ar_dev
&& p
->stat
.st_dev
== ar_dev
&& p
->stat
.st_ino
== ar_ino
);
151 /* Save archive file inode and device numbers */
153 sys_save_archive_dev_ino ()
155 if (!_isrmt (archive
) && S_ISREG (archive_stat
.st_mode
))
157 ar_dev
= archive_stat
.st_dev
;
158 ar_ino
= archive_stat
.st_ino
;
164 /* Detect if outputting to "/dev/null". */
166 sys_detect_dev_null_output ()
168 static char const dev_null
[] = "/dev/null";
169 struct stat dev_null_stat
;
171 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
172 || (! _isrmt (archive
)
173 && S_ISCHR (archive_stat
.st_mode
)
174 && stat (dev_null
, &dev_null_stat
) == 0
175 && archive_stat
.st_dev
== dev_null_stat
.st_dev
176 && archive_stat
.st_ino
== dev_null_stat
.st_ino
));
179 /* Manage to fully drain a pipe we might be reading, so to not break it on
180 the producer after the EOF block. FIXME: one of these days, GNU tar
181 might become clever enough to just stop working, once there is no more
182 work to do, we might have to revise this area in such time. */
185 sys_drain_input_pipe ()
187 if (access_mode
== ACCESS_READ
188 && ! _isrmt (archive
)
189 && (S_ISFIFO (archive_stat
.st_mode
) || S_ISSOCK (archive_stat
.st_mode
)))
190 while (rmtread (archive
, record_start
->buffer
, record_size
) > 0)
195 sys_wait_for_child (pid_t child_pid
)
201 while (waitpid (child_pid
, &wait_status
, 0) == -1)
204 waitpid_error (use_compress_program_option
);
208 if (WIFSIGNALED (wait_status
))
209 ERROR ((0, 0, _("Child died with signal %d"),
210 WTERMSIG (wait_status
)));
211 else if (WEXITSTATUS (wait_status
) != 0)
212 ERROR ((0, 0, _("Child returned status %d"),
213 WEXITSTATUS (wait_status
)));
221 const char *shell
= getenv ("SHELL");
227 execlp (shell
, "-sh", "-i", (char *) 0);
233 while (waitpid (child
, &wait_status
, 0) == -1)
236 waitpid_error (shell
);
243 sys_compare_uid (struct stat
*a
, struct stat
*b
)
245 return a
->st_uid
== b
->st_uid
;
249 sys_compare_gid (struct stat
*a
, struct stat
*b
)
251 return a
->st_gid
== b
->st_gid
;
255 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
257 return stat_data
->st_dev
== link_data
->st_dev
258 && stat_data
->st_ino
== link_data
->st_ino
;
262 sys_truncate (int fd
)
264 off_t pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
);
265 return pos
< 0 ? -1 : ftruncate (fd
, pos
);
275 /* Return nonzero if NAME is the name of a regular file, or if the file
276 does not exist (so it would be created as a regular file). */
278 is_regular_file (const char *name
)
282 if (stat (name
, &stbuf
) == 0)
283 return S_ISREG (stbuf
.st_mode
);
285 return errno
== ENOENT
;
289 sys_write_archive_buffer (void)
294 while (0 <= (status
= rmtwrite (archive
, record_start
->buffer
+ written
,
295 record_size
- written
)))
298 if (written
== record_size
300 || ! (S_ISFIFO (archive_stat
.st_mode
)
301 || S_ISSOCK (archive_stat
.st_mode
)))
305 return written
? written
: status
;
308 #define PREAD 0 /* read file descriptor from pipe() */
309 #define PWRITE 1 /* write file descriptor from pipe() */
311 /* Duplicate file descriptor FROM into becoming INTO.
312 INTO is closed first and has to be the next available slot. */
314 xdup2 (int from
, int into
)
318 int status
= close (into
);
320 if (status
!= 0 && errno
!= EBADF
)
323 FATAL_ERROR ((0, e
, _("Cannot close")));
331 FATAL_ERROR ((0, e
, _("Cannot dup")));
339 /* Set ARCHIVE for writing, then compressing an archive. */
341 sys_child_open_for_compress (void)
345 pid_t grandchild_pid
;
350 child_pid
= xfork ();
354 /* The parent tar is still here! Just clean up. */
356 archive
= parent_pipe
[PWRITE
];
357 xclose (parent_pipe
[PREAD
]);
361 /* The new born child tar is here! */
363 program_name
= _("tar (child)");
365 xdup2 (parent_pipe
[PREAD
], STDIN_FILENO
);
366 xclose (parent_pipe
[PWRITE
]);
368 /* Check if we need a grandchild tar. This happens only if either:
369 a) we are writing stdout: to force reblocking;
370 b) the file is to be accessed by rmt: compressor doesn't know how;
371 c) the file is not a plain file. */
373 if (strcmp (archive_name_array
[0], "-") != 0
374 && !_remdev (archive_name_array
[0])
375 && is_regular_file (archive_name_array
[0]))
378 maybe_backup_file (archive_name_array
[0], 1);
380 /* We don't need a grandchild tar. Open the archive and launch the
383 archive
= creat (archive_name_array
[0], MODE_RW
);
386 int saved_errno
= errno
;
391 open_fatal (archive_name_array
[0]);
393 xdup2 (archive
, STDOUT_FILENO
);
394 execlp (use_compress_program_option
, use_compress_program_option
,
396 exec_fatal (use_compress_program_option
);
399 /* We do need a grandchild tar. */
402 grandchild_pid
= xfork ();
404 if (grandchild_pid
== 0)
406 /* The newborn grandchild tar is here! Launch the compressor. */
408 program_name
= _("tar (grandchild)");
410 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
411 xclose (child_pipe
[PREAD
]);
412 execlp (use_compress_program_option
, use_compress_program_option
,
414 exec_fatal (use_compress_program_option
);
417 /* The child tar is still here! */
419 /* Prepare for reblocking the data from the compressor into the archive. */
421 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
422 xclose (child_pipe
[PWRITE
]);
424 if (strcmp (archive_name_array
[0], "-") == 0)
425 archive
= STDOUT_FILENO
;
428 archive
= rmtcreat (archive_name_array
[0], MODE_RW
, rsh_command_option
);
430 open_fatal (archive_name_array
[0]);
433 /* Let's read out of the stdin pipe and write an archive. */
441 /* Assemble a record. */
443 for (length
= 0, cursor
= record_start
->buffer
;
444 length
< record_size
;
445 length
+= status
, cursor
+= status
)
447 size_t size
= record_size
- length
;
449 status
= safe_read (STDIN_FILENO
, cursor
, size
);
455 read_fatal (use_compress_program_option
);
457 /* Copy the record. */
461 /* We hit the end of the file. Write last record at
462 full length, as the only role of the grandchild is
463 doing proper reblocking. */
467 memset (record_start
->buffer
+ length
, 0, record_size
- length
);
468 status
= sys_write_archive_buffer ();
469 if (status
!= record_size
)
470 archive_write_error (status
);
473 /* There is nothing else to read, break out. */
477 status
= sys_write_archive_buffer ();
478 if (status
!= record_size
)
479 archive_write_error (status
);
482 /* Propagate any failure of the grandchild back to the parent. */
484 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
487 waitpid_error (use_compress_program_option
);
491 if (WIFSIGNALED (wait_status
))
493 kill (child_pid
, WTERMSIG (wait_status
));
494 exit_status
= TAREXIT_FAILURE
;
496 else if (WEXITSTATUS (wait_status
) != 0)
497 exit_status
= WEXITSTATUS (wait_status
);
502 /* Set ARCHIVE for uncompressing, then reading an archive. */
504 sys_child_open_for_uncompress (void)
508 pid_t grandchild_pid
;
513 child_pid
= xfork ();
517 /* The parent tar is still here! Just clean up. */
519 read_full_records_option
= 1;
520 archive
= parent_pipe
[PREAD
];
521 xclose (parent_pipe
[PWRITE
]);
525 /* The newborn child tar is here! */
527 program_name
= _("tar (child)");
529 xdup2 (parent_pipe
[PWRITE
], STDOUT_FILENO
);
530 xclose (parent_pipe
[PREAD
]);
532 /* Check if we need a grandchild tar. This happens only if either:
533 a) we're reading stdin: to force unblocking;
534 b) the file is to be accessed by rmt: compressor doesn't know how;
535 c) the file is not a plain file. */
537 if (strcmp (archive_name_array
[0], "-") != 0
538 && !_remdev (archive_name_array
[0])
539 && is_regular_file (archive_name_array
[0]))
541 /* We don't need a grandchild tar. Open the archive and lauch the
544 archive
= open (archive_name_array
[0], O_RDONLY
| O_BINARY
, MODE_RW
);
546 open_fatal (archive_name_array
[0]);
547 xdup2 (archive
, STDIN_FILENO
);
548 execlp (use_compress_program_option
, use_compress_program_option
,
550 exec_fatal (use_compress_program_option
);
553 /* We do need a grandchild tar. */
556 grandchild_pid
= xfork ();
558 if (grandchild_pid
== 0)
560 /* The newborn grandchild tar is here! Launch the uncompressor. */
562 program_name
= _("tar (grandchild)");
564 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
565 xclose (child_pipe
[PWRITE
]);
566 execlp (use_compress_program_option
, use_compress_program_option
,
568 exec_fatal (use_compress_program_option
);
571 /* The child tar is still here! */
573 /* Prepare for unblocking the data from the archive into the
576 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
577 xclose (child_pipe
[PREAD
]);
579 if (strcmp (archive_name_array
[0], "-") == 0)
580 archive
= STDIN_FILENO
;
582 archive
= rmtopen (archive_name_array
[0], O_RDONLY
| O_BINARY
,
583 MODE_RW
, rsh_command_option
);
585 open_fatal (archive_name_array
[0]);
587 /* Let's read the archive and pipe it into stdout. */
596 clear_read_error_count ();
599 status
= rmtread (archive
, record_start
->buffer
, record_size
);
602 archive_read_error ();
607 cursor
= record_start
->buffer
;
611 count
= maximum
< BLOCKSIZE
? maximum
: BLOCKSIZE
;
612 if (full_write (STDOUT_FILENO
, cursor
, count
) != count
)
613 write_error (use_compress_program_option
);
619 xclose (STDOUT_FILENO
);
621 /* Propagate any failure of the grandchild back to the parent. */
623 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
626 waitpid_error (use_compress_program_option
);
630 if (WIFSIGNALED (wait_status
))
632 kill (child_pid
, WTERMSIG (wait_status
));
633 exit_status
= TAREXIT_FAILURE
;
635 else if (WEXITSTATUS (wait_status
) != 0)
636 exit_status
= WEXITSTATUS (wait_status
);
641 #endif /* not MSDOS */