]> git.cworth.org Git - tar/blob - src/system.c
Imported Upstream version 1.20
[tar] / src / system.c
1 /* System-dependent calls for tar.
2
3    Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4
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 3, or (at your option) any later
8    version.
9
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.
14
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    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18
19 #include <system.h>
20
21 #include "common.h"
22 #include <rmt.h>
23 #include <signal.h>
24
25 #if MSDOS
26
27 bool
28 sys_get_archive_stat (void)
29 {
30   return 0;
31 }
32
33 bool
34 sys_file_is_archive (struct tar_stat_info *p)
35 {
36   return false;
37 }
38
39 void
40 sys_save_archive_dev_ino (void)
41 {
42 }
43
44 void
45 sys_detect_dev_null_output (void)
46 {
47   static char const dev_null[] = "nul";
48
49   dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
50                      || (! _isrmt (archive)));
51 }
52
53 void
54 sys_drain_input_pipe (void)
55 {
56 }
57
58 void
59 sys_wait_for_child (pid_t child_pid)
60 {
61 }
62
63 void
64 sys_spawn_shell (void)
65 {
66   spawnl (P_WAIT, getenv ("COMSPEC"), "-", 0);
67 }
68
69 /* stat() in djgpp's C library gives a constant number of 42 as the
70    uid and gid of a file.  So, comparing an FTP'ed archive just after
71    unpack would fail on MSDOS.  */
72
73 bool
74 sys_compare_uid (struct stat *a, struct stat *b)
75 {
76   return true;
77 }
78
79 bool
80 sys_compare_gid (struct stat *a, struct stat *b)
81 {
82   return true;
83 }
84
85 void
86 sys_compare_links (struct stat *link_data, struct stat *stat_data)
87 {
88   return true;
89 }
90
91 int
92 sys_truncate (int fd)
93 {
94   return write (fd, "", 0);
95 }
96
97 size_t
98 sys_write_archive_buffer (void)
99 {
100   return full_write (archive, record_start->buffer, record_size);
101 }
102
103 /* Set ARCHIVE for writing, then compressing an archive.  */
104 void
105 sys_child_open_for_compress (void)
106 {
107   FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
108 }
109
110 /* Set ARCHIVE for uncompressing, then reading an archive.  */
111 void
112 sys_child_open_for_uncompress (void)
113 {
114   FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
115 }
116
117 #else
118
119 extern union block *record_start; /* FIXME */
120
121 static struct stat archive_stat; /* stat block for archive file */
122
123 bool
124 sys_get_archive_stat (void)
125 {
126   return fstat (archive, &archive_stat) == 0;
127 }
128
129 bool
130 sys_file_is_archive (struct tar_stat_info *p)
131 {
132   return (ar_dev && p->stat.st_dev == ar_dev && p->stat.st_ino == ar_ino);
133 }
134
135 /* Save archive file inode and device numbers */
136 void
137 sys_save_archive_dev_ino (void)
138 {
139   if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
140     {
141       ar_dev = archive_stat.st_dev;
142       ar_ino = archive_stat.st_ino;
143     }
144   else
145     ar_dev = 0;
146 }
147
148 /* Detect if outputting to "/dev/null".  */
149 void
150 sys_detect_dev_null_output (void)
151 {
152   static char const dev_null[] = "/dev/null";
153   struct stat dev_null_stat;
154
155   dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
156                      || (! _isrmt (archive)
157                          && S_ISCHR (archive_stat.st_mode)
158                          && stat (dev_null, &dev_null_stat) == 0
159                          && archive_stat.st_dev == dev_null_stat.st_dev
160                          && archive_stat.st_ino == dev_null_stat.st_ino));
161 }
162
163 /* Manage to fully drain a pipe we might be reading, so to not break it on
164    the producer after the EOF block.  FIXME: one of these days, GNU tar
165    might become clever enough to just stop working, once there is no more
166    work to do, we might have to revise this area in such time.  */
167
168 void
169 sys_drain_input_pipe (void)
170 {
171   size_t r;
172
173   if (access_mode == ACCESS_READ
174       && ! _isrmt (archive)
175       && (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
176     while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
177            && r != SAFE_READ_ERROR)
178       continue;
179 }
180
181 void
182 sys_wait_for_child (pid_t child_pid)
183 {
184   if (child_pid)
185     {
186       int wait_status;
187
188       while (waitpid (child_pid, &wait_status, 0) == -1)
189         if (errno != EINTR)
190           {
191             waitpid_error (use_compress_program_option);
192             break;
193           }
194
195       if (WIFSIGNALED (wait_status))
196         ERROR ((0, 0, _("Child died with signal %d"),
197                 WTERMSIG (wait_status)));
198       else if (WEXITSTATUS (wait_status) != 0)
199         ERROR ((0, 0, _("Child returned status %d"),
200                 WEXITSTATUS (wait_status)));
201     }
202 }
203
204 void
205 sys_spawn_shell (void)
206 {
207   pid_t child;
208   const char *shell = getenv ("SHELL");
209   if (! shell)
210     shell = "/bin/sh";
211   child = xfork ();
212   if (child == 0)
213     {
214       execlp (shell, "-sh", "-i", (char *) 0);
215       exec_fatal (shell);
216     }
217   else
218     {
219       int wait_status;
220       while (waitpid (child, &wait_status, 0) == -1)
221         if (errno != EINTR)
222           {
223             waitpid_error (shell);
224             break;
225           }
226     }
227 }
228
229 bool
230 sys_compare_uid (struct stat *a, struct stat *b)
231 {
232   return a->st_uid == b->st_uid;
233 }
234
235 bool
236 sys_compare_gid (struct stat *a, struct stat *b)
237 {
238   return a->st_gid == b->st_gid;
239 }
240
241 bool
242 sys_compare_links (struct stat *link_data, struct stat *stat_data)
243 {
244   return stat_data->st_dev == link_data->st_dev
245          && stat_data->st_ino == link_data->st_ino;
246 }
247
248 int
249 sys_truncate (int fd)
250 {
251   off_t pos = lseek (fd, (off_t) 0, SEEK_CUR);
252   return pos < 0 ? -1 : ftruncate (fd, pos);
253 }
254
255 /* Return nonzero if NAME is the name of a regular file, or if the file
256    does not exist (so it would be created as a regular file).  */
257 static int
258 is_regular_file (const char *name)
259 {
260   struct stat stbuf;
261
262   if (stat (name, &stbuf) == 0)
263     return S_ISREG (stbuf.st_mode);
264   else
265     return errno == ENOENT;
266 }
267
268 size_t
269 sys_write_archive_buffer (void)
270 {
271   return rmtwrite (archive, record_start->buffer, record_size);
272 }
273
274 #define PREAD 0                 /* read file descriptor from pipe() */
275 #define PWRITE 1                /* write file descriptor from pipe() */
276
277 /* Duplicate file descriptor FROM into becoming INTO.
278    INTO is closed first and has to be the next available slot.  */
279 static void
280 xdup2 (int from, int into)
281 {
282   if (from != into)
283     {
284       int status = close (into);
285
286       if (status != 0 && errno != EBADF)
287         {
288           int e = errno;
289           FATAL_ERROR ((0, e, _("Cannot close")));
290         }
291       status = dup (from);
292       if (status != into)
293         {
294           if (status < 0)
295             {
296               int e = errno;
297               FATAL_ERROR ((0, e, _("Cannot dup")));
298             }
299           abort ();
300         }
301       xclose (from);
302     }
303 }
304
305 /* Set ARCHIVE for writing, then compressing an archive.  */
306 pid_t
307 sys_child_open_for_compress (void)
308 {
309   int parent_pipe[2];
310   int child_pipe[2];
311   pid_t grandchild_pid;
312   pid_t child_pid;
313   int wait_status;
314
315   xpipe (parent_pipe);
316   child_pid = xfork ();
317
318   if (child_pid > 0)
319     {
320       /* The parent tar is still here!  Just clean up.  */
321
322       archive = parent_pipe[PWRITE];
323       xclose (parent_pipe[PREAD]);
324       return child_pid;
325     }
326
327   /* The new born child tar is here!  */
328
329   program_name = _("tar (child)");
330
331   xdup2 (parent_pipe[PREAD], STDIN_FILENO);
332   xclose (parent_pipe[PWRITE]);
333
334   /* Check if we need a grandchild tar.  This happens only if either:
335      a) the file is to be accessed by rmt: compressor doesn't know how;
336      b) the file is not a plain file.  */
337
338   if (!_remdev (archive_name_array[0])
339       && is_regular_file (archive_name_array[0]))
340     {
341       if (backup_option)
342         maybe_backup_file (archive_name_array[0], 1);
343
344       /* We don't need a grandchild tar.  Open the archive and launch the
345          compressor.  */
346       if (strcmp (archive_name_array[0], "-"))
347         {
348           archive = creat (archive_name_array[0], MODE_RW);
349           if (archive < 0)
350             {
351               int saved_errno = errno;
352
353               if (backup_option)
354                 undo_last_backup ();
355               errno = saved_errno;
356               open_fatal (archive_name_array[0]);
357             }
358           xdup2 (archive, STDOUT_FILENO);
359         }
360       execlp (use_compress_program_option, use_compress_program_option, NULL);
361       exec_fatal (use_compress_program_option);
362     }
363
364   /* We do need a grandchild tar.  */
365
366   xpipe (child_pipe);
367   grandchild_pid = xfork ();
368
369   if (grandchild_pid == 0)
370     {
371       /* The newborn grandchild tar is here!  Launch the compressor.  */
372
373       program_name = _("tar (grandchild)");
374
375       xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
376       xclose (child_pipe[PREAD]);
377       execlp (use_compress_program_option, use_compress_program_option,
378               (char *) 0);
379       exec_fatal (use_compress_program_option);
380     }
381
382   /* The child tar is still here!  */
383
384   /* Prepare for reblocking the data from the compressor into the archive.  */
385
386   xdup2 (child_pipe[PREAD], STDIN_FILENO);
387   xclose (child_pipe[PWRITE]);
388
389   if (strcmp (archive_name_array[0], "-") == 0)
390     archive = STDOUT_FILENO;
391   else
392     {
393       archive = rmtcreat (archive_name_array[0], MODE_RW, rsh_command_option);
394       if (archive < 0)
395         open_fatal (archive_name_array[0]);
396     }
397
398   /* Let's read out of the stdin pipe and write an archive.  */
399
400   while (1)
401     {
402       size_t status = 0;
403       char *cursor;
404       size_t length;
405
406       /* Assemble a record.  */
407
408       for (length = 0, cursor = record_start->buffer;
409            length < record_size;
410            length += status, cursor += status)
411         {
412           size_t size = record_size - length;
413
414           status = safe_read (STDIN_FILENO, cursor, size);
415           if (status == SAFE_READ_ERROR)
416             read_fatal (use_compress_program_option);
417           if (status == 0)
418             break;
419         }
420
421       /* Copy the record.  */
422
423       if (status == 0)
424         {
425           /* We hit the end of the file.  Write last record at
426              full length, as the only role of the grandchild is
427              doing proper reblocking.  */
428
429           if (length > 0)
430             {
431               memset (record_start->buffer + length, 0, record_size - length);
432               status = sys_write_archive_buffer ();
433               if (status != record_size)
434                 archive_write_error (status);
435             }
436
437           /* There is nothing else to read, break out.  */
438           break;
439         }
440
441       status = sys_write_archive_buffer ();
442       if (status != record_size)
443         archive_write_error (status);
444     }
445
446   /* Propagate any failure of the grandchild back to the parent.  */
447
448   while (waitpid (grandchild_pid, &wait_status, 0) == -1)
449     if (errno != EINTR)
450       {
451         waitpid_error (use_compress_program_option);
452         break;
453       }
454
455   if (WIFSIGNALED (wait_status))
456     {
457       kill (child_pid, WTERMSIG (wait_status));
458       exit_status = TAREXIT_FAILURE;
459     }
460   else if (WEXITSTATUS (wait_status) != 0)
461     exit_status = WEXITSTATUS (wait_status);
462
463   exit (exit_status);
464 }
465
466 /* Set ARCHIVE for uncompressing, then reading an archive.  */
467 pid_t
468 sys_child_open_for_uncompress (void)
469 {
470   int parent_pipe[2];
471   int child_pipe[2];
472   pid_t grandchild_pid;
473   pid_t child_pid;
474   int wait_status;
475
476   xpipe (parent_pipe);
477   child_pid = xfork ();
478
479   if (child_pid > 0)
480     {
481       /* The parent tar is still here!  Just clean up.  */
482
483       archive = parent_pipe[PREAD];
484       xclose (parent_pipe[PWRITE]);
485       return child_pid;
486     }
487
488   /* The newborn child tar is here!  */
489
490   program_name = _("tar (child)");
491
492   xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
493   xclose (parent_pipe[PREAD]);
494
495   /* Check if we need a grandchild tar.  This happens only if either:
496      a) we're reading stdin: to force unblocking;
497      b) the file is to be accessed by rmt: compressor doesn't know how;
498      c) the file is not a plain file.  */
499
500   if (strcmp (archive_name_array[0], "-") != 0
501       && !_remdev (archive_name_array[0])
502       && is_regular_file (archive_name_array[0]))
503     {
504       /* We don't need a grandchild tar.  Open the archive and lauch the
505          uncompressor.  */
506
507       archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW);
508       if (archive < 0)
509         open_fatal (archive_name_array[0]);
510       xdup2 (archive, STDIN_FILENO);
511       execlp (use_compress_program_option, use_compress_program_option,
512               "-d", (char *) 0);
513       exec_fatal (use_compress_program_option);
514     }
515
516   /* We do need a grandchild tar.  */
517
518   xpipe (child_pipe);
519   grandchild_pid = xfork ();
520
521   if (grandchild_pid == 0)
522     {
523       /* The newborn grandchild tar is here!  Launch the uncompressor.  */
524
525       program_name = _("tar (grandchild)");
526
527       xdup2 (child_pipe[PREAD], STDIN_FILENO);
528       xclose (child_pipe[PWRITE]);
529       execlp (use_compress_program_option, use_compress_program_option,
530               "-d", (char *) 0);
531       exec_fatal (use_compress_program_option);
532     }
533
534   /* The child tar is still here!  */
535
536   /* Prepare for unblocking the data from the archive into the
537      uncompressor.  */
538
539   xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
540   xclose (child_pipe[PREAD]);
541
542   if (strcmp (archive_name_array[0], "-") == 0)
543     archive = STDIN_FILENO;
544   else
545     archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
546                        MODE_RW, rsh_command_option);
547   if (archive < 0)
548     open_fatal (archive_name_array[0]);
549
550   /* Let's read the archive and pipe it into stdout.  */
551
552   while (1)
553     {
554       char *cursor;
555       size_t maximum;
556       size_t count;
557       size_t status;
558
559       clear_read_error_count ();
560
561     error_loop:
562       status = rmtread (archive, record_start->buffer, record_size);
563       if (status == SAFE_READ_ERROR)
564         {
565           archive_read_error ();
566           goto error_loop;
567         }
568       if (status == 0)
569         break;
570       cursor = record_start->buffer;
571       maximum = status;
572       while (maximum)
573         {
574           count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE;
575           if (full_write (STDOUT_FILENO, cursor, count) != count)
576             write_error (use_compress_program_option);
577           cursor += count;
578           maximum -= count;
579         }
580     }
581
582   xclose (STDOUT_FILENO);
583
584   /* Propagate any failure of the grandchild back to the parent.  */
585
586   while (waitpid (grandchild_pid, &wait_status, 0) == -1)
587     if (errno != EINTR)
588       {
589         waitpid_error (use_compress_program_option);
590         break;
591       }
592
593   if (WIFSIGNALED (wait_status))
594     {
595       kill (child_pid, WTERMSIG (wait_status));
596       exit_status = TAREXIT_FAILURE;
597     }
598   else if (WEXITSTATUS (wait_status) != 0)
599     exit_status = WEXITSTATUS (wait_status);
600
601   exit (exit_status);
602 }
603
604 \f
605
606 static void
607 dec_to_env (char *envar, uintmax_t num)
608 {
609   char buf[UINTMAX_STRSIZE_BOUND];
610   char *numstr;
611
612   numstr = STRINGIFY_BIGINT (num, buf);
613   if (setenv (envar, numstr, 1) != 0)
614     xalloc_die ();
615 }
616
617 static void
618 time_to_env (char *envar, struct timespec t)
619 {
620   char buf[TIMESPEC_STRSIZE_BOUND];
621   if (setenv (envar, code_timespec (t, buf), 1) != 0)
622     xalloc_die ();
623 }
624
625 static void
626 oct_to_env (char *envar, unsigned long num)
627 {
628   char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
629
630   snprintf (buf, sizeof buf, "0%lo", num);
631   if (setenv (envar, buf, 1) != 0)
632     xalloc_die ();
633 }
634
635 static void
636 str_to_env (char *envar, char const *str)
637 {
638   if (str)
639     {
640       if (setenv (envar, str, 1) != 0)
641         xalloc_die ();
642     }
643   else
644     unsetenv (envar);
645 }
646
647 static void
648 chr_to_env (char *envar, char c)
649 {
650   char buf[2];
651   buf[0] = c;
652   buf[1] = 0;
653   if (setenv (envar, buf, 1) != 0)
654     xalloc_die ();
655 }
656
657 static void
658 stat_to_env (char *name, char type, struct tar_stat_info *st)
659 {
660   str_to_env ("TAR_VERSION", PACKAGE_VERSION);
661   chr_to_env ("TAR_FILETYPE", type);
662   oct_to_env ("TAR_MODE", st->stat.st_mode);
663   str_to_env ("TAR_FILENAME", name);
664   str_to_env ("TAR_REALNAME", st->file_name);
665   str_to_env ("TAR_UNAME", st->uname);
666   str_to_env ("TAR_GNAME", st->gname);
667   time_to_env ("TAR_ATIME", st->atime);
668   time_to_env ("TAR_MTIME", st->mtime);
669   time_to_env ("TAR_CTIME", st->ctime);
670   dec_to_env ("TAR_SIZE", st->stat.st_size);
671   dec_to_env ("TAR_UID", st->stat.st_uid);
672   dec_to_env ("TAR_GID", st->stat.st_gid);
673
674   switch (type)
675     {
676     case 'b':
677     case 'c':
678       dec_to_env ("TAR_MINOR", minor (st->stat.st_rdev));
679       dec_to_env ("TAR_MAJOR", major (st->stat.st_rdev));
680       unsetenv ("TAR_LINKNAME");
681       break;
682
683     case 'l':
684     case 'h':
685       unsetenv ("TAR_MINOR");
686       unsetenv ("TAR_MAJOR");
687       str_to_env ("TAR_LINKNAME", st->link_name);
688       break;
689
690     default:
691       unsetenv ("TAR_MINOR");
692       unsetenv ("TAR_MAJOR");
693       unsetenv ("TAR_LINKNAME");
694       break;
695     }
696 }
697
698 static pid_t global_pid;
699 static RETSIGTYPE (*pipe_handler) (int sig);
700
701 int
702 sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
703 {
704   int p[2];
705   char *argv[4];
706
707   xpipe (p);
708   pipe_handler = signal (SIGPIPE, SIG_IGN);
709   global_pid = xfork ();
710
711   if (global_pid != 0)
712     {
713       xclose (p[PREAD]);
714       return p[PWRITE];
715     }
716
717   /* Child */
718   xdup2 (p[PREAD], STDIN_FILENO);
719   xclose (p[PWRITE]);
720
721   stat_to_env (file_name, typechar, st);
722
723   argv[0] = "/bin/sh";
724   argv[1] = "-c";
725   argv[2] = to_command_option;
726   argv[3] = NULL;
727
728   execv ("/bin/sh", argv);
729
730   exec_fatal (file_name);
731 }
732
733 void
734 sys_wait_command (void)
735 {
736   int status;
737
738   if (global_pid < 0)
739     return;
740
741   signal (SIGPIPE, pipe_handler);
742   while (waitpid (global_pid, &status, 0) == -1)
743     if (errno != EINTR)
744       {
745         global_pid = -1;
746         waitpid_error (to_command_option);
747         return;
748       }
749
750   if (WIFEXITED (status))
751     {
752       if (!ignore_command_error_option && WEXITSTATUS (status))
753         ERROR ((0, 0, _("%lu: Child returned status %d"),
754                 (unsigned long) global_pid, WEXITSTATUS (status)));
755     }
756   else if (WIFSIGNALED (status))
757     {
758       WARN ((0, 0, _("%lu: Child terminated on signal %d"),
759              (unsigned long) global_pid, WTERMSIG (status)));
760     }
761   else
762     ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
763             (unsigned long) global_pid));
764
765   global_pid = -1;
766 }
767
768 int
769 sys_exec_info_script (const char **archive_name, int volume_number)
770 {
771   pid_t pid;
772   char *argv[4];
773   char uintbuf[UINTMAX_STRSIZE_BOUND];
774   int p[2];
775   static RETSIGTYPE (*saved_handler) (int sig);
776   
777   xpipe (p);
778   saved_handler = signal (SIGPIPE, SIG_IGN);
779
780   pid = xfork ();
781
782   if (pid != 0)
783     {
784       /* Master */
785
786       int rc;
787       int status;
788       char *buf = NULL;
789       size_t size = 0;
790       FILE *fp;
791
792       xclose (p[PWRITE]);
793       fp = fdopen (p[PREAD], "r");
794       rc = getline (&buf, &size, fp);
795       fclose (fp);
796
797       if (rc > 0 && buf[rc-1] == '\n')
798         buf[--rc] = 0;
799
800       while (waitpid (pid, &status, 0) == -1)
801         if (errno != EINTR)
802           {
803             signal (SIGPIPE, saved_handler);
804             waitpid_error (info_script_option);
805             return -1;
806           }
807
808       signal (SIGPIPE, saved_handler);
809       
810       if (WIFEXITED (status))
811         {
812           if (WEXITSTATUS (status) == 0 && rc > 0)
813             *archive_name = buf;
814           else
815             free (buf);
816           return WEXITSTATUS (status);
817         }
818
819       free (buf);
820       return -1;
821     }
822
823   /* Child */
824   setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
825   setenv ("TAR_ARCHIVE", *archive_name, 1);
826   setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
827   setenv ("TAR_BLOCKING_FACTOR",
828           STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
829   setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
830   setenv ("TAR_FORMAT",
831           archive_format_string (current_format == DEFAULT_FORMAT ?
832                                  archive_format : current_format), 1);
833   setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
834
835   xclose (p[PREAD]);
836
837   argv[0] = "/bin/sh";
838   argv[1] = "-c";
839   argv[2] = (char*) info_script_option;
840   argv[3] = NULL;
841
842   execv (argv[0], argv);
843
844   exec_fatal (info_script_option);
845 }
846
847 void
848 sys_exec_checkpoint_script (const char *script_name,
849                             const char *archive_name,
850                             int checkpoint_number)
851 {
852   pid_t pid;
853   char *argv[4];
854   char uintbuf[UINTMAX_STRSIZE_BOUND];
855
856   pid = xfork ();
857
858   if (pid != 0)
859     {
860       /* Master */
861
862       int status;
863
864       while (waitpid (pid, &status, 0) == -1)
865         if (errno != EINTR)
866           {
867             waitpid_error (script_name);
868             break;
869           }
870
871       return;
872     }
873
874   /* Child */
875   setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
876   setenv ("TAR_ARCHIVE", archive_name, 1);
877   setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1);
878   setenv ("TAR_BLOCKING_FACTOR",
879           STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
880   setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
881   setenv ("TAR_FORMAT",
882           archive_format_string (current_format == DEFAULT_FORMAT ?
883                                  archive_format : current_format), 1);
884   argv[0] = "/bin/sh";
885   argv[1] = "-c";
886   argv[2] = (char*) script_name;
887   argv[3] = NULL;
888
889   execv (argv[0], argv);
890
891   exec_fatal (script_name);
892 }
893
894 #endif /* not MSDOS */