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);
70 sys_compare_uid_gid (struct stat
*a
, struct stat
*b
)
72 /* stat() in djgpp's C library gives a constant number of 42 as the
73 uid and gid of a file. So, comparing an FTP'ed archive just after
74 unpack would fail on MSDOS. */
78 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
85 return write (fd
, "", 0);
94 sys_write_archive_buffer (void)
99 while (0 <= (status
= full_write (archive
, record_start
->buffer
+ written
,
100 record_size
- written
)))
103 if (written
== record_size
)
107 return written
? written
: status
;
110 /* Set ARCHIVE for writing, then compressing an archive. */
112 sys_child_open_for_compress (void)
114 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
117 /* Set ARCHIVE for uncompressing, then reading an archive. */
119 sys_child_open_for_uncompress (void)
121 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
126 extern union block
*record_start
; /* FIXME */
128 static struct stat archive_stat
; /* stat block for archive file */
131 sys_get_archive_stat ()
133 return fstat (archive
, &archive_stat
) == 0;
137 sys_file_is_archive (struct tar_stat_info
*p
)
139 return (ar_dev
&& p
->stat
.st_dev
== ar_dev
&& p
->stat
.st_ino
== ar_ino
);
142 /* Save archive file inode and device numbers */
144 sys_save_archive_dev_ino ()
146 if (!_isrmt (archive
) && S_ISREG (archive_stat
.st_mode
))
148 ar_dev
= archive_stat
.st_dev
;
149 ar_ino
= archive_stat
.st_ino
;
155 /* Detect if outputting to "/dev/null". */
157 sys_detect_dev_null_output ()
159 static char const dev_null
[] = "/dev/null";
160 struct stat dev_null_stat
;
162 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
163 || (! _isrmt (archive
)
164 && S_ISCHR (archive_stat
.st_mode
)
165 && stat (dev_null
, &dev_null_stat
) == 0
166 && archive_stat
.st_dev
== dev_null_stat
.st_dev
167 && archive_stat
.st_ino
== dev_null_stat
.st_ino
));
170 /* Manage to fully drain a pipe we might be reading, so to not break it on
171 the producer after the EOF block. FIXME: one of these days, GNU tar
172 might become clever enough to just stop working, once there is no more
173 work to do, we might have to revise this area in such time. */
176 sys_drain_input_pipe ()
178 if (access_mode
== ACCESS_READ
179 && ! _isrmt (archive
)
180 && (S_ISFIFO (archive_stat
.st_mode
) || S_ISSOCK (archive_stat
.st_mode
)))
181 while (rmtread (archive
, record_start
->buffer
, record_size
) > 0)
186 sys_wait_for_child (pid_t child_pid
)
192 while (waitpid (child_pid
, &wait_status
, 0) == -1)
195 waitpid_error (use_compress_program_option
);
199 if (WIFSIGNALED (wait_status
))
200 ERROR ((0, 0, _("Child died with signal %d"),
201 WTERMSIG (wait_status
)));
202 else if (WEXITSTATUS (wait_status
) != 0)
203 ERROR ((0, 0, _("Child returned status %d"),
204 WEXITSTATUS (wait_status
)));
212 const char *shell
= getenv ("SHELL");
218 execlp (shell
, "-sh", "-i", (char *) 0);
224 while (waitpid (child
, &wait_status
, 0) == -1)
227 waitpid_error (shell
);
234 sys_compare_uid_gid (struct stat
*a
, struct stat
*b
)
236 if (a
->st_uid
!= b
->st_uid
)
237 report_difference (_("Uid differs"));
238 if (a
->st_gid
!= b
->st_gid
)
239 report_difference (_("Gid differs"));
243 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
245 if (stat_data
->st_dev
!= link_data
->st_dev
246 || stat_data
->st_ino
!= link_data
->st_ino
)
248 report_difference (_("Not linked to %s"),
249 quote (current_stat_info
.link_name
));
254 sys_truncate (int fd
)
256 off_t pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
);
257 return pos
< 0 ? -1 : ftruncate (fd
, pos
);
267 /* Return nonzero if NAME is the name of a regular file, or if the file
268 does not exist (so it would be created as a regular file). */
270 is_regular_file (const char *name
)
274 if (stat (name
, &stbuf
) == 0)
275 return S_ISREG (stbuf
.st_mode
);
277 return errno
== ENOENT
;
281 sys_write_archive_buffer (void)
286 while (0 <= (status
= rmtwrite (archive
, record_start
->buffer
+ written
,
287 record_size
- written
)))
290 if (written
== record_size
292 || ! (S_ISFIFO (archive_stat
.st_mode
)
293 || S_ISSOCK (archive_stat
.st_mode
)))
297 return written
? written
: status
;
300 #define PREAD 0 /* read file descriptor from pipe() */
301 #define PWRITE 1 /* write file descriptor from pipe() */
303 /* Duplicate file descriptor FROM into becoming INTO.
304 INTO is closed first and has to be the next available slot. */
306 xdup2 (int from
, int into
)
310 int status
= close (into
);
312 if (status
!= 0 && errno
!= EBADF
)
315 FATAL_ERROR ((0, e
, _("Cannot close")));
323 FATAL_ERROR ((0, e
, _("Cannot dup")));
331 /* Set ARCHIVE for writing, then compressing an archive. */
333 sys_child_open_for_compress (void)
337 pid_t grandchild_pid
;
342 child_pid
= xfork ();
346 /* The parent tar is still here! Just clean up. */
348 archive
= parent_pipe
[PWRITE
];
349 xclose (parent_pipe
[PREAD
]);
353 /* The new born child tar is here! */
355 program_name
= _("tar (child)");
357 xdup2 (parent_pipe
[PREAD
], STDIN_FILENO
);
358 xclose (parent_pipe
[PWRITE
]);
360 /* Check if we need a grandchild tar. This happens only if either:
361 a) we are writing stdout: to force reblocking;
362 b) the file is to be accessed by rmt: compressor doesn't know how;
363 c) the file is not a plain file. */
365 if (strcmp (archive_name_array
[0], "-") != 0
366 && !_remdev (archive_name_array
[0])
367 && is_regular_file (archive_name_array
[0]))
370 maybe_backup_file (archive_name_array
[0], 1);
372 /* We don't need a grandchild tar. Open the archive and launch the
375 archive
= creat (archive_name_array
[0], MODE_RW
);
378 int saved_errno
= errno
;
383 open_fatal (archive_name_array
[0]);
385 xdup2 (archive
, STDOUT_FILENO
);
386 execlp (use_compress_program_option
, use_compress_program_option
,
388 exec_fatal (use_compress_program_option
);
391 /* We do need a grandchild tar. */
394 grandchild_pid
= xfork ();
396 if (grandchild_pid
== 0)
398 /* The newborn grandchild tar is here! Launch the compressor. */
400 program_name
= _("tar (grandchild)");
402 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
403 xclose (child_pipe
[PREAD
]);
404 execlp (use_compress_program_option
, use_compress_program_option
,
406 exec_fatal (use_compress_program_option
);
409 /* The child tar is still here! */
411 /* Prepare for reblocking the data from the compressor into the archive. */
413 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
414 xclose (child_pipe
[PWRITE
]);
416 if (strcmp (archive_name_array
[0], "-") == 0)
417 archive
= STDOUT_FILENO
;
420 archive
= rmtcreat (archive_name_array
[0], MODE_RW
, rsh_command_option
);
422 open_fatal (archive_name_array
[0]);
425 /* Let's read out of the stdin pipe and write an archive. */
433 /* Assemble a record. */
435 for (length
= 0, cursor
= record_start
->buffer
;
436 length
< record_size
;
437 length
+= status
, cursor
+= status
)
439 size_t size
= record_size
- length
;
441 status
= safe_read (STDIN_FILENO
, cursor
, size
);
447 read_fatal (use_compress_program_option
);
449 /* Copy the record. */
453 /* We hit the end of the file. Write last record at
454 full length, as the only role of the grandchild is
455 doing proper reblocking. */
459 memset (record_start
->buffer
+ length
, 0, record_size
- length
);
460 status
= sys_write_archive_buffer ();
461 if (status
!= record_size
)
462 archive_write_error (status
);
465 /* There is nothing else to read, break out. */
469 status
= sys_write_archive_buffer ();
470 if (status
!= record_size
)
471 archive_write_error (status
);
474 /* Propagate any failure of the grandchild back to the parent. */
476 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
479 waitpid_error (use_compress_program_option
);
483 if (WIFSIGNALED (wait_status
))
485 kill (child_pid
, WTERMSIG (wait_status
));
486 exit_status
= TAREXIT_FAILURE
;
488 else if (WEXITSTATUS (wait_status
) != 0)
489 exit_status
= WEXITSTATUS (wait_status
);
494 /* Set ARCHIVE for uncompressing, then reading an archive. */
496 sys_child_open_for_uncompress (void)
500 pid_t grandchild_pid
;
505 child_pid
= xfork ();
509 /* The parent tar is still here! Just clean up. */
511 read_full_records_option
= 1;
512 archive
= parent_pipe
[PREAD
];
513 xclose (parent_pipe
[PWRITE
]);
517 /* The newborn child tar is here! */
519 program_name
= _("tar (child)");
521 xdup2 (parent_pipe
[PWRITE
], STDOUT_FILENO
);
522 xclose (parent_pipe
[PREAD
]);
524 /* Check if we need a grandchild tar. This happens only if either:
525 a) we're reading stdin: to force unblocking;
526 b) the file is to be accessed by rmt: compressor doesn't know how;
527 c) the file is not a plain file. */
529 if (strcmp (archive_name_array
[0], "-") != 0
530 && !_remdev (archive_name_array
[0])
531 && is_regular_file (archive_name_array
[0]))
533 /* We don't need a grandchild tar. Open the archive and lauch the
536 archive
= open (archive_name_array
[0], O_RDONLY
| O_BINARY
, MODE_RW
);
538 open_fatal (archive_name_array
[0]);
539 xdup2 (archive
, STDIN_FILENO
);
540 execlp (use_compress_program_option
, use_compress_program_option
,
542 exec_fatal (use_compress_program_option
);
545 /* We do need a grandchild tar. */
548 grandchild_pid
= xfork ();
550 if (grandchild_pid
== 0)
552 /* The newborn grandchild tar is here! Launch the uncompressor. */
554 program_name
= _("tar (grandchild)");
556 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
557 xclose (child_pipe
[PWRITE
]);
558 execlp (use_compress_program_option
, use_compress_program_option
,
560 exec_fatal (use_compress_program_option
);
563 /* The child tar is still here! */
565 /* Prepare for unblocking the data from the archive into the
568 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
569 xclose (child_pipe
[PREAD
]);
571 if (strcmp (archive_name_array
[0], "-") == 0)
572 archive
= STDIN_FILENO
;
574 archive
= rmtopen (archive_name_array
[0], O_RDONLY
| O_BINARY
,
575 MODE_RW
, rsh_command_option
);
577 open_fatal (archive_name_array
[0]);
579 /* Let's read the archive and pipe it into stdout. */
588 clear_read_error_count ();
591 status
= rmtread (archive
, record_start
->buffer
, record_size
);
594 archive_read_error ();
599 cursor
= record_start
->buffer
;
603 count
= maximum
< BLOCKSIZE
? maximum
: BLOCKSIZE
;
604 if (full_write (STDOUT_FILENO
, cursor
, count
) != count
)
605 write_error (use_compress_program_option
);
611 xclose (STDOUT_FILENO
);
613 /* Propagate any failure of the grandchild back to the parent. */
615 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
618 waitpid_error (use_compress_program_option
);
622 if (WIFSIGNALED (wait_status
))
624 kill (child_pid
, WTERMSIG (wait_status
));
625 exit_status
= TAREXIT_FAILURE
;
627 else if (WEXITSTATUS (wait_status
) != 0)
628 exit_status
= WEXITSTATUS (wait_status
);
633 #endif /* not MSDOS */