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. */
26 sys_stat_nanoseconds(struct tar_stat_info
*stat
)
28 #if defined(HAVE_STRUCT_STAT_ST_SPARE1)
29 stat
->atime_nsec
= stat
->stat
.st_spare1
* 1000;
30 stat
->mtime_nsec
= stat
->stat
.st_spare2
* 1000;
31 stat
->ctime_nsec
= stat
->stat
.st_spare3
* 1000;
32 #elif defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
33 stat
->atime_nsec
= stat
->stat
.st_atim
.tv_nsec
;
34 stat
->mtime_nsec
= stat
->stat
.st_mtim
.tv_nsec
;
35 stat
->ctime_nsec
= stat
->stat
.st_ctim
.tv_nsec
;
36 #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
37 stat
->atime_nsec
= stat
->stat
.st_atimespec
.tv_nsec
;
38 stat
->mtime_nsec
= stat
->stat
.st_mtimespec
.tv_nsec
;
39 stat
->ctime_nsec
= stat
->stat
.st_ctimespec
.tv_nsec
;
40 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
41 stat
->atime_nsec
= stat
->stat
.st_atimensec
;
42 stat
->mtime_nsec
= stat
->stat
.st_mtimensec
;
43 stat
->ctime_nsec
= stat
->stat
.st_ctimensec
;
45 stat
->atime_nsec
= stat
->mtime_nsec
= stat
->ctime_nsec
= 0;
50 sys_utimes(char *file_name
, struct timeval tvp
[3])
53 return utimes (file_name
, tvp
);
55 struct utimbuf utimbuf
;
56 utimbuf
.actime
= tvp
[0].tv_sec
;
57 utimbuf
.modtime
= tvp
[1].tv_sec
;
58 return utime (file_name
, &utimbuf
);
65 sys_get_archive_stat ()
71 sys_file_is_archive (struct tar_stat_info
*p
)
77 sys_save_archive_dev_ino ()
82 sys_detect_dev_null_output ()
84 static char const dev_null
[] = "nul";
86 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
87 || (! _isrmt (archive
)));
91 sys_drain_input_pipe ()
96 sys_wait_for_child (pid_t child_pid
)
103 spawnl (P_WAIT
, getenv ("COMSPEC"), "-", 0);
106 /* stat() in djgpp's C library gives a constant number of 42 as the
107 uid and gid of a file. So, comparing an FTP'ed archive just after
108 unpack would fail on MSDOS. */
111 sys_compare_uid (struct stat
*a
, struct stat
*b
)
117 sys_compare_gid (struct stat
*a
, struct stat
*b
)
123 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
129 sys_truncate (int fd
)
131 return write (fd
, "", 0);
140 sys_write_archive_buffer (void)
145 while (0 <= (status
= full_write (archive
, record_start
->buffer
+ written
,
146 record_size
- written
)))
149 if (written
== record_size
)
153 return written
? written
: status
;
156 /* Set ARCHIVE for writing, then compressing an archive. */
158 sys_child_open_for_compress (void)
160 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
163 /* Set ARCHIVE for uncompressing, then reading an archive. */
165 sys_child_open_for_uncompress (void)
167 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
172 extern union block
*record_start
; /* FIXME */
174 static struct stat archive_stat
; /* stat block for archive file */
177 sys_get_archive_stat ()
179 return fstat (archive
, &archive_stat
) == 0;
183 sys_file_is_archive (struct tar_stat_info
*p
)
185 return (ar_dev
&& p
->stat
.st_dev
== ar_dev
&& p
->stat
.st_ino
== ar_ino
);
188 /* Save archive file inode and device numbers */
190 sys_save_archive_dev_ino ()
192 if (!_isrmt (archive
) && S_ISREG (archive_stat
.st_mode
))
194 ar_dev
= archive_stat
.st_dev
;
195 ar_ino
= archive_stat
.st_ino
;
201 /* Detect if outputting to "/dev/null". */
203 sys_detect_dev_null_output ()
205 static char const dev_null
[] = "/dev/null";
206 struct stat dev_null_stat
;
208 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
209 || (! _isrmt (archive
)
210 && S_ISCHR (archive_stat
.st_mode
)
211 && stat (dev_null
, &dev_null_stat
) == 0
212 && archive_stat
.st_dev
== dev_null_stat
.st_dev
213 && archive_stat
.st_ino
== dev_null_stat
.st_ino
));
216 /* Manage to fully drain a pipe we might be reading, so to not break it on
217 the producer after the EOF block. FIXME: one of these days, GNU tar
218 might become clever enough to just stop working, once there is no more
219 work to do, we might have to revise this area in such time. */
222 sys_drain_input_pipe ()
224 if (access_mode
== ACCESS_READ
225 && ! _isrmt (archive
)
226 && (S_ISFIFO (archive_stat
.st_mode
) || S_ISSOCK (archive_stat
.st_mode
)))
227 while (rmtread (archive
, record_start
->buffer
, record_size
) > 0)
232 sys_wait_for_child (pid_t child_pid
)
238 while (waitpid (child_pid
, &wait_status
, 0) == -1)
241 waitpid_error (use_compress_program_option
);
245 if (WIFSIGNALED (wait_status
))
246 ERROR ((0, 0, _("Child died with signal %d"),
247 WTERMSIG (wait_status
)));
248 else if (WEXITSTATUS (wait_status
) != 0)
249 ERROR ((0, 0, _("Child returned status %d"),
250 WEXITSTATUS (wait_status
)));
258 const char *shell
= getenv ("SHELL");
264 execlp (shell
, "-sh", "-i", (char *) 0);
270 while (waitpid (child
, &wait_status
, 0) == -1)
273 waitpid_error (shell
);
280 sys_compare_uid (struct stat
*a
, struct stat
*b
)
282 return a
->st_uid
== b
->st_uid
;
286 sys_compare_gid (struct stat
*a
, struct stat
*b
)
288 return a
->st_gid
== b
->st_gid
;
292 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
294 return stat_data
->st_dev
== link_data
->st_dev
295 && stat_data
->st_ino
== link_data
->st_ino
;
299 sys_truncate (int fd
)
301 off_t pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
);
302 return pos
< 0 ? -1 : ftruncate (fd
, pos
);
312 /* Return nonzero if NAME is the name of a regular file, or if the file
313 does not exist (so it would be created as a regular file). */
315 is_regular_file (const char *name
)
319 if (stat (name
, &stbuf
) == 0)
320 return S_ISREG (stbuf
.st_mode
);
322 return errno
== ENOENT
;
326 sys_write_archive_buffer (void)
331 while (0 <= (status
= rmtwrite (archive
, record_start
->buffer
+ written
,
332 record_size
- written
)))
335 if (written
== record_size
337 || ! (S_ISFIFO (archive_stat
.st_mode
)
338 || S_ISSOCK (archive_stat
.st_mode
)))
342 return written
? written
: status
;
345 #define PREAD 0 /* read file descriptor from pipe() */
346 #define PWRITE 1 /* write file descriptor from pipe() */
348 /* Duplicate file descriptor FROM into becoming INTO.
349 INTO is closed first and has to be the next available slot. */
351 xdup2 (int from
, int into
)
355 int status
= close (into
);
357 if (status
!= 0 && errno
!= EBADF
)
360 FATAL_ERROR ((0, e
, _("Cannot close")));
368 FATAL_ERROR ((0, e
, _("Cannot dup")));
376 /* Set ARCHIVE for writing, then compressing an archive. */
378 sys_child_open_for_compress (void)
382 pid_t grandchild_pid
;
387 child_pid
= xfork ();
391 /* The parent tar is still here! Just clean up. */
393 archive
= parent_pipe
[PWRITE
];
394 xclose (parent_pipe
[PREAD
]);
398 /* The new born child tar is here! */
400 program_name
= _("tar (child)");
402 xdup2 (parent_pipe
[PREAD
], STDIN_FILENO
);
403 xclose (parent_pipe
[PWRITE
]);
405 /* Check if we need a grandchild tar. This happens only if either:
406 a) we are writing stdout: to force reblocking;
407 b) the file is to be accessed by rmt: compressor doesn't know how;
408 c) the file is not a plain file. */
410 if (strcmp (archive_name_array
[0], "-") != 0
411 && !_remdev (archive_name_array
[0])
412 && is_regular_file (archive_name_array
[0]))
415 maybe_backup_file (archive_name_array
[0], 1);
417 /* We don't need a grandchild tar. Open the archive and launch the
420 archive
= creat (archive_name_array
[0], MODE_RW
);
423 int saved_errno
= errno
;
428 open_fatal (archive_name_array
[0]);
430 xdup2 (archive
, STDOUT_FILENO
);
431 execlp (use_compress_program_option
, use_compress_program_option
,
433 exec_fatal (use_compress_program_option
);
436 /* We do need a grandchild tar. */
439 grandchild_pid
= xfork ();
441 if (grandchild_pid
== 0)
443 /* The newborn grandchild tar is here! Launch the compressor. */
445 program_name
= _("tar (grandchild)");
447 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
448 xclose (child_pipe
[PREAD
]);
449 execlp (use_compress_program_option
, use_compress_program_option
,
451 exec_fatal (use_compress_program_option
);
454 /* The child tar is still here! */
456 /* Prepare for reblocking the data from the compressor into the archive. */
458 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
459 xclose (child_pipe
[PWRITE
]);
461 if (strcmp (archive_name_array
[0], "-") == 0)
462 archive
= STDOUT_FILENO
;
465 archive
= rmtcreat (archive_name_array
[0], MODE_RW
, rsh_command_option
);
467 open_fatal (archive_name_array
[0]);
470 /* Let's read out of the stdin pipe and write an archive. */
478 /* Assemble a record. */
480 for (length
= 0, cursor
= record_start
->buffer
;
481 length
< record_size
;
482 length
+= status
, cursor
+= status
)
484 size_t size
= record_size
- length
;
486 status
= safe_read (STDIN_FILENO
, cursor
, size
);
492 read_fatal (use_compress_program_option
);
494 /* Copy the record. */
498 /* We hit the end of the file. Write last record at
499 full length, as the only role of the grandchild is
500 doing proper reblocking. */
504 memset (record_start
->buffer
+ length
, 0, record_size
- length
);
505 status
= sys_write_archive_buffer ();
506 if (status
!= record_size
)
507 archive_write_error (status
);
510 /* There is nothing else to read, break out. */
514 status
= sys_write_archive_buffer ();
515 if (status
!= record_size
)
516 archive_write_error (status
);
519 /* Propagate any failure of the grandchild back to the parent. */
521 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
524 waitpid_error (use_compress_program_option
);
528 if (WIFSIGNALED (wait_status
))
530 kill (child_pid
, WTERMSIG (wait_status
));
531 exit_status
= TAREXIT_FAILURE
;
533 else if (WEXITSTATUS (wait_status
) != 0)
534 exit_status
= WEXITSTATUS (wait_status
);
539 /* Set ARCHIVE for uncompressing, then reading an archive. */
541 sys_child_open_for_uncompress (void)
545 pid_t grandchild_pid
;
550 child_pid
= xfork ();
554 /* The parent tar is still here! Just clean up. */
556 read_full_records_option
= 1;
557 archive
= parent_pipe
[PREAD
];
558 xclose (parent_pipe
[PWRITE
]);
562 /* The newborn child tar is here! */
564 program_name
= _("tar (child)");
566 xdup2 (parent_pipe
[PWRITE
], STDOUT_FILENO
);
567 xclose (parent_pipe
[PREAD
]);
569 /* Check if we need a grandchild tar. This happens only if either:
570 a) we're reading stdin: to force unblocking;
571 b) the file is to be accessed by rmt: compressor doesn't know how;
572 c) the file is not a plain file. */
574 if (strcmp (archive_name_array
[0], "-") != 0
575 && !_remdev (archive_name_array
[0])
576 && is_regular_file (archive_name_array
[0]))
578 /* We don't need a grandchild tar. Open the archive and lauch the
581 archive
= open (archive_name_array
[0], O_RDONLY
| O_BINARY
, MODE_RW
);
583 open_fatal (archive_name_array
[0]);
584 xdup2 (archive
, STDIN_FILENO
);
585 execlp (use_compress_program_option
, use_compress_program_option
,
587 exec_fatal (use_compress_program_option
);
590 /* We do need a grandchild tar. */
593 grandchild_pid
= xfork ();
595 if (grandchild_pid
== 0)
597 /* The newborn grandchild tar is here! Launch the uncompressor. */
599 program_name
= _("tar (grandchild)");
601 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
602 xclose (child_pipe
[PWRITE
]);
603 execlp (use_compress_program_option
, use_compress_program_option
,
605 exec_fatal (use_compress_program_option
);
608 /* The child tar is still here! */
610 /* Prepare for unblocking the data from the archive into the
613 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
614 xclose (child_pipe
[PREAD
]);
616 if (strcmp (archive_name_array
[0], "-") == 0)
617 archive
= STDIN_FILENO
;
619 archive
= rmtopen (archive_name_array
[0], O_RDONLY
| O_BINARY
,
620 MODE_RW
, rsh_command_option
);
622 open_fatal (archive_name_array
[0]);
624 /* Let's read the archive and pipe it into stdout. */
633 clear_read_error_count ();
636 status
= rmtread (archive
, record_start
->buffer
, record_size
);
639 archive_read_error ();
644 cursor
= record_start
->buffer
;
648 count
= maximum
< BLOCKSIZE
? maximum
: BLOCKSIZE
;
649 if (full_write (STDOUT_FILENO
, cursor
, count
) != count
)
650 write_error (use_compress_program_option
);
656 xclose (STDOUT_FILENO
);
658 /* Propagate any failure of the grandchild back to the parent. */
660 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
663 waitpid_error (use_compress_program_option
);
667 if (WIFSIGNALED (wait_status
))
669 kill (child_pid
, WTERMSIG (wait_status
));
670 exit_status
= TAREXIT_FAILURE
;
672 else if (WEXITSTATUS (wait_status
) != 0)
673 exit_status
= WEXITSTATUS (wait_status
);
678 #endif /* not MSDOS */