1 /* System-dependent calls for tar.
3 Copyright (C) 2003, 2004 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
*st
)
28 #if defined(HAVE_STRUCT_STAT_ST_SPARE1)
29 st
->atime_nsec
= st
->stat
.st_spare1
* 1000;
30 st
->mtime_nsec
= st
->stat
.st_spare2
* 1000;
31 st
->ctime_nsec
= st
->stat
.st_spare3
* 1000;
32 #elif defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
33 st
->atime_nsec
= st
->stat
.st_atim
.tv_nsec
;
34 st
->mtime_nsec
= st
->stat
.st_mtim
.tv_nsec
;
35 st
->ctime_nsec
= st
->stat
.st_ctim
.tv_nsec
;
36 #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
37 st
->atime_nsec
= st
->stat
.st_atimespec
.tv_nsec
;
38 st
->mtime_nsec
= st
->stat
.st_mtimespec
.tv_nsec
;
39 st
->ctime_nsec
= st
->stat
.st_ctimespec
.tv_nsec
;
40 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
41 st
->atime_nsec
= st
->stat
.st_atimensec
;
42 st
->mtime_nsec
= st
->stat
.st_mtimensec
;
43 st
->ctime_nsec
= st
->stat
.st_ctimensec
;
45 st
->atime_nsec
= st
->mtime_nsec
= st
->ctime_nsec
= 0;
52 sys_get_archive_stat (void)
58 sys_file_is_archive (struct tar_stat_info
*p
)
64 sys_save_archive_dev_ino (void)
69 sys_detect_dev_null_output (void)
71 static char const dev_null
[] = "nul";
73 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
74 || (! _isrmt (archive
)));
78 sys_drain_input_pipe (void)
83 sys_wait_for_child (pid_t child_pid
)
88 sys_spawn_shell (void)
90 spawnl (P_WAIT
, getenv ("COMSPEC"), "-", 0);
93 /* stat() in djgpp's C library gives a constant number of 42 as the
94 uid and gid of a file. So, comparing an FTP'ed archive just after
95 unpack would fail on MSDOS. */
98 sys_compare_uid (struct stat
*a
, struct stat
*b
)
104 sys_compare_gid (struct stat
*a
, struct stat
*b
)
110 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
116 sys_truncate (int fd
)
118 return write (fd
, "", 0);
122 sys_reset_uid_gid (void)
127 sys_write_archive_buffer (void)
129 return full_write (archive
, record_start
->buffer
, record_size
);
132 /* Set ARCHIVE for writing, then compressing an archive. */
134 sys_child_open_for_compress (void)
136 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
139 /* Set ARCHIVE for uncompressing, then reading an archive. */
141 sys_child_open_for_uncompress (void)
143 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
148 extern union block
*record_start
; /* FIXME */
150 static struct stat archive_stat
; /* stat block for archive file */
153 sys_get_archive_stat (void)
155 return fstat (archive
, &archive_stat
) == 0;
159 sys_file_is_archive (struct tar_stat_info
*p
)
161 return (ar_dev
&& p
->stat
.st_dev
== ar_dev
&& p
->stat
.st_ino
== ar_ino
);
164 /* Save archive file inode and device numbers */
166 sys_save_archive_dev_ino (void)
168 if (!_isrmt (archive
) && S_ISREG (archive_stat
.st_mode
))
170 ar_dev
= archive_stat
.st_dev
;
171 ar_ino
= archive_stat
.st_ino
;
177 /* Detect if outputting to "/dev/null". */
179 sys_detect_dev_null_output (void)
181 static char const dev_null
[] = "/dev/null";
182 struct stat dev_null_stat
;
184 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
185 || (! _isrmt (archive
)
186 && S_ISCHR (archive_stat
.st_mode
)
187 && stat (dev_null
, &dev_null_stat
) == 0
188 && archive_stat
.st_dev
== dev_null_stat
.st_dev
189 && archive_stat
.st_ino
== dev_null_stat
.st_ino
));
192 /* Manage to fully drain a pipe we might be reading, so to not break it on
193 the producer after the EOF block. FIXME: one of these days, GNU tar
194 might become clever enough to just stop working, once there is no more
195 work to do, we might have to revise this area in such time. */
198 sys_drain_input_pipe (void)
202 if (access_mode
== ACCESS_READ
203 && ! _isrmt (archive
)
204 && (S_ISFIFO (archive_stat
.st_mode
) || S_ISSOCK (archive_stat
.st_mode
)))
205 while ((r
= rmtread (archive
, record_start
->buffer
, record_size
)) != 0
206 && r
!= SAFE_READ_ERROR
)
211 sys_wait_for_child (pid_t child_pid
)
217 while (waitpid (child_pid
, &wait_status
, 0) == -1)
220 waitpid_error (use_compress_program_option
);
224 if (WIFSIGNALED (wait_status
))
225 ERROR ((0, 0, _("Child died with signal %d"),
226 WTERMSIG (wait_status
)));
227 else if (WEXITSTATUS (wait_status
) != 0)
228 ERROR ((0, 0, _("Child returned status %d"),
229 WEXITSTATUS (wait_status
)));
234 sys_spawn_shell (void)
237 const char *shell
= getenv ("SHELL");
243 execlp (shell
, "-sh", "-i", (char *) 0);
249 while (waitpid (child
, &wait_status
, 0) == -1)
252 waitpid_error (shell
);
259 sys_compare_uid (struct stat
*a
, struct stat
*b
)
261 return a
->st_uid
== b
->st_uid
;
265 sys_compare_gid (struct stat
*a
, struct stat
*b
)
267 return a
->st_gid
== b
->st_gid
;
271 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
273 return stat_data
->st_dev
== link_data
->st_dev
274 && stat_data
->st_ino
== link_data
->st_ino
;
278 sys_truncate (int fd
)
280 off_t pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
);
281 return pos
< 0 ? -1 : ftruncate (fd
, pos
);
285 sys_reset_uid_gid (void)
291 /* Return nonzero if NAME is the name of a regular file, or if the file
292 does not exist (so it would be created as a regular file). */
294 is_regular_file (const char *name
)
298 if (stat (name
, &stbuf
) == 0)
299 return S_ISREG (stbuf
.st_mode
);
301 return errno
== ENOENT
;
305 sys_write_archive_buffer (void)
307 return rmtwrite (archive
, record_start
->buffer
, record_size
);
310 #define PREAD 0 /* read file descriptor from pipe() */
311 #define PWRITE 1 /* write file descriptor from pipe() */
313 /* Duplicate file descriptor FROM into becoming INTO.
314 INTO is closed first and has to be the next available slot. */
316 xdup2 (int from
, int into
)
320 int status
= close (into
);
322 if (status
!= 0 && errno
!= EBADF
)
325 FATAL_ERROR ((0, e
, _("Cannot close")));
333 FATAL_ERROR ((0, e
, _("Cannot dup")));
341 /* Set ARCHIVE for writing, then compressing an archive. */
343 sys_child_open_for_compress (void)
347 pid_t grandchild_pid
;
352 child_pid
= xfork ();
356 /* The parent tar is still here! Just clean up. */
358 archive
= parent_pipe
[PWRITE
];
359 xclose (parent_pipe
[PREAD
]);
363 /* The new born child tar is here! */
365 program_name
= _("tar (child)");
367 xdup2 (parent_pipe
[PREAD
], STDIN_FILENO
);
368 xclose (parent_pipe
[PWRITE
]);
370 /* Check if we need a grandchild tar. This happens only if either:
371 a) we are writing stdout: to force reblocking;
372 b) the file is to be accessed by rmt: compressor doesn't know how;
373 c) the file is not a plain file. */
375 if (strcmp (archive_name_array
[0], "-") != 0
376 && !_remdev (archive_name_array
[0])
377 && is_regular_file (archive_name_array
[0]))
380 maybe_backup_file (archive_name_array
[0], 1);
382 /* We don't need a grandchild tar. Open the archive and launch the
385 archive
= creat (archive_name_array
[0], MODE_RW
);
388 int saved_errno
= errno
;
393 open_fatal (archive_name_array
[0]);
395 xdup2 (archive
, STDOUT_FILENO
);
396 execlp (use_compress_program_option
, use_compress_program_option
,
398 exec_fatal (use_compress_program_option
);
401 /* We do need a grandchild tar. */
404 grandchild_pid
= xfork ();
406 if (grandchild_pid
== 0)
408 /* The newborn grandchild tar is here! Launch the compressor. */
410 program_name
= _("tar (grandchild)");
412 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
413 xclose (child_pipe
[PREAD
]);
414 execlp (use_compress_program_option
, use_compress_program_option
,
416 exec_fatal (use_compress_program_option
);
419 /* The child tar is still here! */
421 /* Prepare for reblocking the data from the compressor into the archive. */
423 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
424 xclose (child_pipe
[PWRITE
]);
426 if (strcmp (archive_name_array
[0], "-") == 0)
427 archive
= STDOUT_FILENO
;
430 archive
= rmtcreat (archive_name_array
[0], MODE_RW
, rsh_command_option
);
432 open_fatal (archive_name_array
[0]);
435 /* Let's read out of the stdin pipe and write an archive. */
443 /* Assemble a record. */
445 for (length
= 0, cursor
= record_start
->buffer
;
446 length
< record_size
;
447 length
+= status
, cursor
+= status
)
449 size_t size
= record_size
- length
;
451 status
= safe_read (STDIN_FILENO
, cursor
, size
);
452 if (status
== SAFE_READ_ERROR
)
453 read_fatal (use_compress_program_option
);
458 /* Copy the record. */
462 /* We hit the end of the file. Write last record at
463 full length, as the only role of the grandchild is
464 doing proper reblocking. */
468 memset (record_start
->buffer
+ length
, 0, record_size
- length
);
469 status
= sys_write_archive_buffer ();
470 if (status
!= record_size
)
471 archive_write_error (status
);
474 /* There is nothing else to read, break out. */
478 status
= sys_write_archive_buffer ();
479 if (status
!= record_size
)
480 archive_write_error (status
);
483 /* Propagate any failure of the grandchild back to the parent. */
485 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
488 waitpid_error (use_compress_program_option
);
492 if (WIFSIGNALED (wait_status
))
494 kill (child_pid
, WTERMSIG (wait_status
));
495 exit_status
= TAREXIT_FAILURE
;
497 else if (WEXITSTATUS (wait_status
) != 0)
498 exit_status
= WEXITSTATUS (wait_status
);
503 /* Set ARCHIVE for uncompressing, then reading an archive. */
505 sys_child_open_for_uncompress (void)
509 pid_t grandchild_pid
;
514 child_pid
= xfork ();
518 /* The parent tar is still here! Just clean up. */
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
);
600 if (status
== SAFE_READ_ERROR
)
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 */