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. */
27 sys_get_archive_stat ()
33 sys_file_is_archive (struct tar_stat_info
*p
)
39 sys_save_archive_dev_ino ()
44 sys_detect_dev_null_output ()
46 static char const dev_null
[] = "nul";
48 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
49 || (! _isrmt (archive
)));
53 sys_drain_input_pipe ()
58 sys_wait_for_child (pid_t child_pid
)
65 spawnl (P_WAIT
, getenv ("COMSPEC"), "-", 0);
69 sys_compare_uid_gid (struct stat
*a
, struct stat
*b
)
71 /* stat() in djgpp's C library gives a constant number of 42 as the
72 uid and gid of a file. So, comparing an FTP'ed archive just after
73 unpack would fail on MSDOS. */
77 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
84 return write (fd
, "", 0);
93 sys_write_archive_buffer (void)
98 while (0 <= (status
= full_write (archive
, record_start
->buffer
+ written
,
99 record_size
- written
)))
102 if (written
== record_size
)
106 return written
? written
: status
;
109 /* Set ARCHIVE for writing, then compressing an archive. */
111 sys_child_open_for_compress (void)
113 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
116 /* Set ARCHIVE for uncompressing, then reading an archive. */
118 sys_child_open_for_uncompress (void)
120 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
125 extern union block
*record_start
; /* FIXME */
127 static struct stat archive_stat
; /* stat block for archive file */
130 sys_get_archive_stat ()
132 return fstat (archive
, &archive_stat
) == 0;
136 sys_file_is_archive (struct tar_stat_info
*p
)
138 return (ar_dev
&& p
->stat
.st_dev
== ar_dev
&& p
->stat
.st_ino
== ar_ino
);
141 /* Save archive file inode and device numbers */
143 sys_save_archive_dev_ino ()
145 if (!_isrmt (archive
) && S_ISREG (archive_stat
.st_mode
))
147 ar_dev
= archive_stat
.st_dev
;
148 ar_ino
= archive_stat
.st_ino
;
154 /* Detect if outputting to "/dev/null". */
156 sys_detect_dev_null_output ()
158 static char const dev_null
[] = "/dev/null";
159 struct stat dev_null_stat
;
161 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
162 || (! _isrmt (archive
)
163 && S_ISCHR (archive_stat
.st_mode
)
164 && stat (dev_null
, &dev_null_stat
) == 0
165 && archive_stat
.st_dev
== dev_null_stat
.st_dev
166 && archive_stat
.st_ino
== dev_null_stat
.st_ino
));
169 /* Manage to fully drain a pipe we might be reading, so to not break it on
170 the producer after the EOF block. FIXME: one of these days, GNU tar
171 might become clever enough to just stop working, once there is no more
172 work to do, we might have to revise this area in such time. */
175 sys_drain_input_pipe ()
177 if (access_mode
== ACCESS_READ
178 && ! _isrmt (archive
)
179 && (S_ISFIFO (archive_stat
.st_mode
) || S_ISSOCK (archive_stat
.st_mode
)))
180 while (rmtread (archive
, record_start
->buffer
, record_size
) > 0)
185 sys_wait_for_child (pid_t child_pid
)
191 while (waitpid (child_pid
, &wait_status
, 0) == -1)
194 waitpid_error (use_compress_program_option
);
198 if (WIFSIGNALED (wait_status
))
199 ERROR ((0, 0, _("Child died with signal %d"),
200 WTERMSIG (wait_status
)));
201 else if (WEXITSTATUS (wait_status
) != 0)
202 ERROR ((0, 0, _("Child returned status %d"),
203 WEXITSTATUS (wait_status
)));
211 const char *shell
= getenv ("SHELL");
217 execlp (shell
, "-sh", "-i", (char *) 0);
223 while (waitpid (child
, &wait_status
, 0) == -1)
226 waitpid_error (shell
);
233 sys_compare_uid_gid (struct stat
*a
, struct stat
*b
)
235 if (a
->st_uid
!= b
->st_uid
)
236 report_difference (_("Uid differs"));
237 if (a
->st_gid
!= b
->st_gid
)
238 report_difference (_("Gid differs"));
242 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
244 if (stat_data
->st_dev
!= link_data
->st_dev
245 || stat_data
->st_ino
!= link_data
->st_ino
)
247 report_difference (_("Not linked to %s"),
248 quote (current_stat_info
.link_name
));
253 sys_truncate (int fd
)
255 off_t pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
);
256 return pos
< 0 ? -1 : ftruncate (fd
, pos
);
266 /* Return nonzero if NAME is the name of a regular file, or if the file
267 does not exist (so it would be created as a regular file). */
269 is_regular_file (const char *name
)
273 if (stat (name
, &stbuf
) == 0)
274 return S_ISREG (stbuf
.st_mode
);
276 return errno
== ENOENT
;
280 sys_write_archive_buffer (void)
285 while (0 <= (status
= rmtwrite (archive
, record_start
->buffer
+ written
,
286 record_size
- written
)))
289 if (written
== record_size
291 || ! (S_ISFIFO (archive_stat
.st_mode
)
292 || S_ISSOCK (archive_stat
.st_mode
)))
296 return written
? written
: status
;
299 #define PREAD 0 /* read file descriptor from pipe() */
300 #define PWRITE 1 /* write file descriptor from pipe() */
302 /* Duplicate file descriptor FROM into becoming INTO.
303 INTO is closed first and has to be the next available slot. */
305 xdup2 (int from
, int into
)
309 int status
= close (into
);
311 if (status
!= 0 && errno
!= EBADF
)
314 FATAL_ERROR ((0, e
, _("Cannot close")));
322 FATAL_ERROR ((0, e
, _("Cannot dup")));
330 /* Set ARCHIVE for writing, then compressing an archive. */
332 sys_child_open_for_compress (void)
336 pid_t grandchild_pid
;
341 child_pid
= xfork ();
345 /* The parent tar is still here! Just clean up. */
347 archive
= parent_pipe
[PWRITE
];
348 xclose (parent_pipe
[PREAD
]);
352 /* The new born child tar is here! */
354 program_name
= _("tar (child)");
356 xdup2 (parent_pipe
[PREAD
], STDIN_FILENO
);
357 xclose (parent_pipe
[PWRITE
]);
359 /* Check if we need a grandchild tar. This happens only if either:
360 a) we are writing stdout: to force reblocking;
361 b) the file is to be accessed by rmt: compressor doesn't know how;
362 c) the file is not a plain file. */
364 if (strcmp (archive_name_array
[0], "-") != 0
365 && !_remdev (archive_name_array
[0])
366 && is_regular_file (archive_name_array
[0]))
369 maybe_backup_file (archive_name_array
[0], 1);
371 /* We don't need a grandchild tar. Open the archive and launch the
374 archive
= creat (archive_name_array
[0], MODE_RW
);
377 int saved_errno
= errno
;
382 open_fatal (archive_name_array
[0]);
384 xdup2 (archive
, STDOUT_FILENO
);
385 execlp (use_compress_program_option
, use_compress_program_option
,
387 exec_fatal (use_compress_program_option
);
390 /* We do need a grandchild tar. */
393 grandchild_pid
= xfork ();
395 if (grandchild_pid
== 0)
397 /* The newborn grandchild tar is here! Launch the compressor. */
399 program_name
= _("tar (grandchild)");
401 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
402 xclose (child_pipe
[PREAD
]);
403 execlp (use_compress_program_option
, use_compress_program_option
,
405 exec_fatal (use_compress_program_option
);
408 /* The child tar is still here! */
410 /* Prepare for reblocking the data from the compressor into the archive. */
412 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
413 xclose (child_pipe
[PWRITE
]);
415 if (strcmp (archive_name_array
[0], "-") == 0)
416 archive
= STDOUT_FILENO
;
419 archive
= rmtcreat (archive_name_array
[0], MODE_RW
, rsh_command_option
);
421 open_fatal (archive_name_array
[0]);
424 /* Let's read out of the stdin pipe and write an archive. */
432 /* Assemble a record. */
434 for (length
= 0, cursor
= record_start
->buffer
;
435 length
< record_size
;
436 length
+= status
, cursor
+= status
)
438 size_t size
= record_size
- length
;
440 status
= safe_read (STDIN_FILENO
, cursor
, size
);
446 read_fatal (use_compress_program_option
);
448 /* Copy the record. */
452 /* We hit the end of the file. Write last record at
453 full length, as the only role of the grandchild is
454 doing proper reblocking. */
458 memset (record_start
->buffer
+ length
, 0, record_size
- length
);
459 status
= sys_write_archive_buffer ();
460 if (status
!= record_size
)
461 archive_write_error (status
);
464 /* There is nothing else to read, break out. */
468 status
= sys_write_archive_buffer ();
469 if (status
!= record_size
)
470 archive_write_error (status
);
473 /* Propagate any failure of the grandchild back to the parent. */
475 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
478 waitpid_error (use_compress_program_option
);
482 if (WIFSIGNALED (wait_status
))
484 kill (child_pid
, WTERMSIG (wait_status
));
485 exit_status
= TAREXIT_FAILURE
;
487 else if (WEXITSTATUS (wait_status
) != 0)
488 exit_status
= WEXITSTATUS (wait_status
);
493 /* Set ARCHIVE for uncompressing, then reading an archive. */
495 sys_child_open_for_uncompress (void)
499 pid_t grandchild_pid
;
504 child_pid
= xfork ();
508 /* The parent tar is still here! Just clean up. */
510 read_full_records_option
= 1;
511 archive
= parent_pipe
[PREAD
];
512 xclose (parent_pipe
[PWRITE
]);
516 /* The newborn child tar is here! */
518 program_name
= _("tar (child)");
520 xdup2 (parent_pipe
[PWRITE
], STDOUT_FILENO
);
521 xclose (parent_pipe
[PREAD
]);
523 /* Check if we need a grandchild tar. This happens only if either:
524 a) we're reading stdin: to force unblocking;
525 b) the file is to be accessed by rmt: compressor doesn't know how;
526 c) the file is not a plain file. */
528 if (strcmp (archive_name_array
[0], "-") != 0
529 && !_remdev (archive_name_array
[0])
530 && is_regular_file (archive_name_array
[0]))
532 /* We don't need a grandchild tar. Open the archive and lauch the
535 archive
= open (archive_name_array
[0], O_RDONLY
| O_BINARY
, MODE_RW
);
537 open_fatal (archive_name_array
[0]);
538 xdup2 (archive
, STDIN_FILENO
);
539 execlp (use_compress_program_option
, use_compress_program_option
,
541 exec_fatal (use_compress_program_option
);
544 /* We do need a grandchild tar. */
547 grandchild_pid
= xfork ();
549 if (grandchild_pid
== 0)
551 /* The newborn grandchild tar is here! Launch the uncompressor. */
553 program_name
= _("tar (grandchild)");
555 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
556 xclose (child_pipe
[PWRITE
]);
557 execlp (use_compress_program_option
, use_compress_program_option
,
559 exec_fatal (use_compress_program_option
);
562 /* The child tar is still here! */
564 /* Prepare for unblocking the data from the archive into the
567 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
568 xclose (child_pipe
[PREAD
]);
570 if (strcmp (archive_name_array
[0], "-") == 0)
571 archive
= STDIN_FILENO
;
573 archive
= rmtopen (archive_name_array
[0], O_RDONLY
| O_BINARY
,
574 MODE_RW
, rsh_command_option
);
576 open_fatal (archive_name_array
[0]);
578 /* Let's read the archive and pipe it into stdout. */
587 clear_read_error_count ();
590 status
= rmtread (archive
, record_start
->buffer
, record_size
);
593 archive_read_error ();
598 cursor
= record_start
->buffer
;
602 count
= maximum
< BLOCKSIZE
? maximum
: BLOCKSIZE
;
603 if (full_write (STDOUT_FILENO
, cursor
, count
) != count
)
604 write_error (use_compress_program_option
);
610 xclose (STDOUT_FILENO
);
612 /* Propagate any failure of the grandchild back to the parent. */
614 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
617 waitpid_error (use_compress_program_option
);
621 if (WIFSIGNALED (wait_status
))
623 kill (child_pid
, WTERMSIG (wait_status
));
624 exit_status
= TAREXIT_FAILURE
;
626 else if (WEXITSTATUS (wait_status
) != 0)
627 exit_status
= WEXITSTATUS (wait_status
);
632 #endif /* not MSDOS */