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_write_archive_buffer (void)
124 return full_write (archive
, record_start
->buffer
, record_size
);
127 /* Set ARCHIVE for writing, then compressing an archive. */
129 sys_child_open_for_compress (void)
131 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
134 /* Set ARCHIVE for uncompressing, then reading an archive. */
136 sys_child_open_for_uncompress (void)
138 FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
143 extern union block
*record_start
; /* FIXME */
145 static struct stat archive_stat
; /* stat block for archive file */
148 sys_get_archive_stat (void)
150 return fstat (archive
, &archive_stat
) == 0;
154 sys_file_is_archive (struct tar_stat_info
*p
)
156 return (ar_dev
&& p
->stat
.st_dev
== ar_dev
&& p
->stat
.st_ino
== ar_ino
);
159 /* Save archive file inode and device numbers */
161 sys_save_archive_dev_ino (void)
163 if (!_isrmt (archive
) && S_ISREG (archive_stat
.st_mode
))
165 ar_dev
= archive_stat
.st_dev
;
166 ar_ino
= archive_stat
.st_ino
;
172 /* Detect if outputting to "/dev/null". */
174 sys_detect_dev_null_output (void)
176 static char const dev_null
[] = "/dev/null";
177 struct stat dev_null_stat
;
179 dev_null_output
= (strcmp (archive_name_array
[0], dev_null
) == 0
180 || (! _isrmt (archive
)
181 && S_ISCHR (archive_stat
.st_mode
)
182 && stat (dev_null
, &dev_null_stat
) == 0
183 && archive_stat
.st_dev
== dev_null_stat
.st_dev
184 && archive_stat
.st_ino
== dev_null_stat
.st_ino
));
187 /* Manage to fully drain a pipe we might be reading, so to not break it on
188 the producer after the EOF block. FIXME: one of these days, GNU tar
189 might become clever enough to just stop working, once there is no more
190 work to do, we might have to revise this area in such time. */
193 sys_drain_input_pipe (void)
197 if (access_mode
== ACCESS_READ
198 && ! _isrmt (archive
)
199 && (S_ISFIFO (archive_stat
.st_mode
) || S_ISSOCK (archive_stat
.st_mode
)))
200 while ((r
= rmtread (archive
, record_start
->buffer
, record_size
)) != 0
201 && r
!= SAFE_READ_ERROR
)
206 sys_wait_for_child (pid_t child_pid
)
212 while (waitpid (child_pid
, &wait_status
, 0) == -1)
215 waitpid_error (use_compress_program_option
);
219 if (WIFSIGNALED (wait_status
))
220 ERROR ((0, 0, _("Child died with signal %d"),
221 WTERMSIG (wait_status
)));
222 else if (WEXITSTATUS (wait_status
) != 0)
223 ERROR ((0, 0, _("Child returned status %d"),
224 WEXITSTATUS (wait_status
)));
229 sys_spawn_shell (void)
232 const char *shell
= getenv ("SHELL");
238 execlp (shell
, "-sh", "-i", (char *) 0);
244 while (waitpid (child
, &wait_status
, 0) == -1)
247 waitpid_error (shell
);
254 sys_compare_uid (struct stat
*a
, struct stat
*b
)
256 return a
->st_uid
== b
->st_uid
;
260 sys_compare_gid (struct stat
*a
, struct stat
*b
)
262 return a
->st_gid
== b
->st_gid
;
266 sys_compare_links (struct stat
*link_data
, struct stat
*stat_data
)
268 return stat_data
->st_dev
== link_data
->st_dev
269 && stat_data
->st_ino
== link_data
->st_ino
;
273 sys_truncate (int fd
)
275 off_t pos
= lseek (fd
, (off_t
) 0, SEEK_CUR
);
276 return pos
< 0 ? -1 : ftruncate (fd
, pos
);
279 /* Return nonzero if NAME is the name of a regular file, or if the file
280 does not exist (so it would be created as a regular file). */
282 is_regular_file (const char *name
)
286 if (stat (name
, &stbuf
) == 0)
287 return S_ISREG (stbuf
.st_mode
);
289 return errno
== ENOENT
;
293 sys_write_archive_buffer (void)
295 return rmtwrite (archive
, record_start
->buffer
, record_size
);
298 #define PREAD 0 /* read file descriptor from pipe() */
299 #define PWRITE 1 /* write file descriptor from pipe() */
301 /* Duplicate file descriptor FROM into becoming INTO.
302 INTO is closed first and has to be the next available slot. */
304 xdup2 (int from
, int into
)
308 int status
= close (into
);
310 if (status
!= 0 && errno
!= EBADF
)
313 FATAL_ERROR ((0, e
, _("Cannot close")));
321 FATAL_ERROR ((0, e
, _("Cannot dup")));
329 /* Set ARCHIVE for writing, then compressing an archive. */
331 sys_child_open_for_compress (void)
335 pid_t grandchild_pid
;
340 child_pid
= xfork ();
344 /* The parent tar is still here! Just clean up. */
346 archive
= parent_pipe
[PWRITE
];
347 xclose (parent_pipe
[PREAD
]);
351 /* The new born child tar is here! */
353 program_name
= _("tar (child)");
355 xdup2 (parent_pipe
[PREAD
], STDIN_FILENO
);
356 xclose (parent_pipe
[PWRITE
]);
358 /* Check if we need a grandchild tar. This happens only if either:
359 a) we are writing stdout: to force reblocking;
360 b) the file is to be accessed by rmt: compressor doesn't know how;
361 c) the file is not a plain file. */
363 if (strcmp (archive_name_array
[0], "-") != 0
364 && !_remdev (archive_name_array
[0])
365 && is_regular_file (archive_name_array
[0]))
368 maybe_backup_file (archive_name_array
[0], 1);
370 /* We don't need a grandchild tar. Open the archive and launch the
373 archive
= creat (archive_name_array
[0], MODE_RW
);
376 int saved_errno
= errno
;
381 open_fatal (archive_name_array
[0]);
383 xdup2 (archive
, STDOUT_FILENO
);
384 execlp (use_compress_program_option
, use_compress_program_option
,
386 exec_fatal (use_compress_program_option
);
389 /* We do need a grandchild tar. */
392 grandchild_pid
= xfork ();
394 if (grandchild_pid
== 0)
396 /* The newborn grandchild tar is here! Launch the compressor. */
398 program_name
= _("tar (grandchild)");
400 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
401 xclose (child_pipe
[PREAD
]);
402 execlp (use_compress_program_option
, use_compress_program_option
,
404 exec_fatal (use_compress_program_option
);
407 /* The child tar is still here! */
409 /* Prepare for reblocking the data from the compressor into the archive. */
411 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
412 xclose (child_pipe
[PWRITE
]);
414 if (strcmp (archive_name_array
[0], "-") == 0)
415 archive
= STDOUT_FILENO
;
418 archive
= rmtcreat (archive_name_array
[0], MODE_RW
, rsh_command_option
);
420 open_fatal (archive_name_array
[0]);
423 /* Let's read out of the stdin pipe and write an archive. */
431 /* Assemble a record. */
433 for (length
= 0, cursor
= record_start
->buffer
;
434 length
< record_size
;
435 length
+= status
, cursor
+= status
)
437 size_t size
= record_size
- length
;
439 status
= safe_read (STDIN_FILENO
, cursor
, size
);
440 if (status
== SAFE_READ_ERROR
)
441 read_fatal (use_compress_program_option
);
446 /* Copy the record. */
450 /* We hit the end of the file. Write last record at
451 full length, as the only role of the grandchild is
452 doing proper reblocking. */
456 memset (record_start
->buffer
+ length
, 0, record_size
- length
);
457 status
= sys_write_archive_buffer ();
458 if (status
!= record_size
)
459 archive_write_error (status
);
462 /* There is nothing else to read, break out. */
466 status
= sys_write_archive_buffer ();
467 if (status
!= record_size
)
468 archive_write_error (status
);
471 /* Propagate any failure of the grandchild back to the parent. */
473 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
476 waitpid_error (use_compress_program_option
);
480 if (WIFSIGNALED (wait_status
))
482 kill (child_pid
, WTERMSIG (wait_status
));
483 exit_status
= TAREXIT_FAILURE
;
485 else if (WEXITSTATUS (wait_status
) != 0)
486 exit_status
= WEXITSTATUS (wait_status
);
491 /* Set ARCHIVE for uncompressing, then reading an archive. */
493 sys_child_open_for_uncompress (void)
497 pid_t grandchild_pid
;
502 child_pid
= xfork ();
506 /* The parent tar is still here! Just clean up. */
508 archive
= parent_pipe
[PREAD
];
509 xclose (parent_pipe
[PWRITE
]);
513 /* The newborn child tar is here! */
515 program_name
= _("tar (child)");
517 xdup2 (parent_pipe
[PWRITE
], STDOUT_FILENO
);
518 xclose (parent_pipe
[PREAD
]);
520 /* Check if we need a grandchild tar. This happens only if either:
521 a) we're reading stdin: to force unblocking;
522 b) the file is to be accessed by rmt: compressor doesn't know how;
523 c) the file is not a plain file. */
525 if (strcmp (archive_name_array
[0], "-") != 0
526 && !_remdev (archive_name_array
[0])
527 && is_regular_file (archive_name_array
[0]))
529 /* We don't need a grandchild tar. Open the archive and lauch the
532 archive
= open (archive_name_array
[0], O_RDONLY
| O_BINARY
, MODE_RW
);
534 open_fatal (archive_name_array
[0]);
535 xdup2 (archive
, STDIN_FILENO
);
536 execlp (use_compress_program_option
, use_compress_program_option
,
538 exec_fatal (use_compress_program_option
);
541 /* We do need a grandchild tar. */
544 grandchild_pid
= xfork ();
546 if (grandchild_pid
== 0)
548 /* The newborn grandchild tar is here! Launch the uncompressor. */
550 program_name
= _("tar (grandchild)");
552 xdup2 (child_pipe
[PREAD
], STDIN_FILENO
);
553 xclose (child_pipe
[PWRITE
]);
554 execlp (use_compress_program_option
, use_compress_program_option
,
556 exec_fatal (use_compress_program_option
);
559 /* The child tar is still here! */
561 /* Prepare for unblocking the data from the archive into the
564 xdup2 (child_pipe
[PWRITE
], STDOUT_FILENO
);
565 xclose (child_pipe
[PREAD
]);
567 if (strcmp (archive_name_array
[0], "-") == 0)
568 archive
= STDIN_FILENO
;
570 archive
= rmtopen (archive_name_array
[0], O_RDONLY
| O_BINARY
,
571 MODE_RW
, rsh_command_option
);
573 open_fatal (archive_name_array
[0]);
575 /* Let's read the archive and pipe it into stdout. */
584 clear_read_error_count ();
587 status
= rmtread (archive
, record_start
->buffer
, record_size
);
588 if (status
== SAFE_READ_ERROR
)
590 archive_read_error ();
595 cursor
= record_start
->buffer
;
599 count
= maximum
< BLOCKSIZE
? maximum
: BLOCKSIZE
;
600 if (full_write (STDOUT_FILENO
, cursor
, count
) != count
)
601 write_error (use_compress_program_option
);
607 xclose (STDOUT_FILENO
);
609 /* Propagate any failure of the grandchild back to the parent. */
611 while (waitpid (grandchild_pid
, &wait_status
, 0) == -1)
614 waitpid_error (use_compress_program_option
);
618 if (WIFSIGNALED (wait_status
))
620 kill (child_pid
, WTERMSIG (wait_status
));
621 exit_status
= TAREXIT_FAILURE
;
623 else if (WEXITSTATUS (wait_status
) != 0)
624 exit_status
= WEXITSTATUS (wait_status
);
629 #endif /* not MSDOS */