*** empty log message ***
[debian/tar] / src / extract.c
1 /* Extract files from a tar archive.
2    Copyright (C) 1988, 1992 Free Software Foundation
3
4 This file is part of GNU Tar.
5
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21  * Extract files from a tar archive.
22  *
23  * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
24  */
25
26 #include <stdio.h>
27 #include <errno.h>
28 #ifndef STDC_HEADERS
29 extern int errno;
30 #endif
31 #include <sys/types.h>
32 #include <time.h>
33 time_t time ();
34
35 #ifdef BSD42
36 #include <sys/file.h>
37 #else
38 #ifndef V7
39 #include <fcntl.h>
40 #endif
41 #endif
42
43 #ifdef NO_OPEN3
44 /* We need the #define's even though we don't use them. */
45 #include "open3.h"
46 #endif
47
48 #ifdef EMUL_OPEN3
49 /* Simulated 3-argument open for systems that don't have it */
50 #include "open3.h"
51 #endif
52
53 #include "tar.h"
54 #include "port.h"
55
56 #if defined(_POSIX_VERSION)
57 #include <utime.h>
58 #else
59 struct utimbuf
60 {
61   long actime;
62   long modtime;
63 };
64
65 #endif
66
67 extern FILE *msg_file;
68
69 extern union record *head;      /* Points to current tape header */
70 extern struct stat hstat;       /* Stat struct corresponding */
71 extern int head_standard;       /* Tape header is in ANSI format */
72
73 extern char *save_name;
74 extern long save_totsize;
75 extern long save_sizeleft;
76
77 int confirm ();
78 void decode_header ();
79 void extract_mangle ();
80 void extract_sparse_file ();
81 long from_oct ();
82 void gnu_restore ();
83 extern void print_header ();
84 extern void skip_file ();
85 extern void skip_extended_headers ();
86 extern void pr_mkdir ();
87 void saverec ();
88
89 int make_dirs ();               /* Makes required directories */
90
91 static time_t now = 0;          /* Current time */
92 static we_are_root = 0;         /* True if our effective uid == 0 */
93 static int notumask = ~0;       /* Masks out bits user doesn't want */
94
95 /*
96  * "Scratch" space to store the information about a sparse file before
97  * writing the info into the header or extended header
98  */
99 /*struct sp_array       *sparsearray;*/
100
101 /* number of elts storable in the sparsearray */
102 /*int   sp_array_size = 10;*/
103
104 struct saved_dir_info
105 {
106   char *path;
107   int mode;
108   int atime;
109   int mtime;
110   struct saved_dir_info *next;
111 };
112
113 struct saved_dir_info *saved_dir_info_head;
114
115 /*
116  * Set up to extract files.
117  */
118 void
119 extr_init ()
120 {
121   int ourmask;
122
123   now = time ((time_t *) 0);
124   if (geteuid () == 0)
125     we_are_root = 1;
126
127   /*
128          * We need to know our umask.  But if f_use_protection is set,
129          * leave our kernel umask at 0, and our "notumask" at ~0.
130          */
131   ourmask = umask (0);          /* Read it */
132   if (!f_use_protection)
133     {
134       (void) umask (ourmask);   /* Set it back how it was */
135       notumask = ~ourmask;      /* Make umask override permissions */
136     }
137 }
138
139
140 /*
141  * Extract a file from the archive.
142  */
143 void
144 extract_archive ()
145 {
146   register char *data;
147   int fd, check, namelen, written, openflag;
148   long size;
149   struct utimbuf acc_upd_times;
150   register int skipcrud;
151   register int i;
152   /*    int sparse_ind = 0;*/
153   union record *exhdr;
154   struct saved_dir_info *tmp;
155   /*    int end_nulls; */
156   char **longp;
157   char *bp;
158
159   saverec (&head);              /* Make sure it sticks around */
160   userec (head);                /* And go past it in the archive */
161   decode_header (head, &hstat, &head_standard, 1);      /* Snarf fields */
162
163   if (f_confirm && !confirm ("extract", current_file_name))
164     {
165       if (head->header.isextended)
166         skip_extended_headers ();
167       skip_file ((long) hstat.st_size);
168       saverec ((union record **) 0);
169       return;
170     }
171
172   /* Print the record from 'head' and 'hstat' */
173   if (f_verbose)
174     print_header ();
175
176   /*
177          * Check for fully specified pathnames and other atrocities.
178          *
179          * Note, we can't just make a pointer to the new file name,
180          * since saverec() might move the header and adjust "head".
181          * We have to start from "head" every time we want to touch
182          * the header record.
183          */
184   skipcrud = 0;
185   while (!f_absolute_paths
186          && '/' == current_file_name[skipcrud])
187     {
188       static int warned_once = 0;
189
190       skipcrud++;               /* Force relative path */
191       if (!warned_once++)
192         {
193           msg ("Removing leading / from absolute path names in the archive.");
194         }
195     }
196
197   switch (head->header.linkflag)
198     {
199
200     default:
201       msg ("Unknown file type '%c' for %s, extracted as normal file",
202            head->header.linkflag, skipcrud + current_file_name);
203       /* FALL THRU */
204
205       /*
206           * JK - What we want to do if the file is sparse is loop through
207           * the array of sparse structures in the header and read in
208           * and translate the character strings representing  1) the offset
209           * at which to write and 2) how many bytes to write into numbers,
210           * which we store into the scratch array, "sparsearray".  This
211           * array makes our life easier the same way it did in creating
212           * the tar file that had to deal with a sparse file.
213           *
214           * After we read in the first five (at most) sparse structures,
215           * we check to see if the file has an extended header, i.e.,
216           * if more sparse structures are needed to describe the contents
217           * of the new file.  If so, we read in the extended headers
218           * and continue to store their contents into the sparsearray.
219           */
220     case LF_SPARSE:
221       sp_array_size = 10;
222       sparsearray = (struct sp_array *) malloc (sp_array_size * sizeof (struct sp_array));
223       for (i = 0; i < SPARSE_IN_HDR; i++)
224         {
225           sparsearray[i].offset =
226             from_oct (1 + 12, head->header.sp[i].offset);
227           sparsearray[i].numbytes =
228             from_oct (1 + 12, head->header.sp[i].numbytes);
229           if (!sparsearray[i].numbytes)
230             break;
231         }
232
233       /*                end_nulls = from_oct(1+12, head->header.ending_blanks);*/
234
235       if (head->header.isextended)
236         {
237           /* read in the list of extended headers
238                             and translate them into the sparsearray
239                             as before */
240
241           /* static */ int ind = SPARSE_IN_HDR;
242
243           for (;;)
244             {
245
246               exhdr = findrec ();
247               for (i = 0; i < SPARSE_EXT_HDR; i++)
248                 {
249
250                   if (i + ind > sp_array_size - 1)
251                     {
252                       /*
253                                           * realloc the scratch area
254                                           * since we've run out of room --
255                                           */
256                       sparsearray = (struct sp_array *)
257                         realloc (sparsearray,
258                             2 * sp_array_size * (sizeof (struct sp_array)));
259                       sp_array_size *= 2;
260                     }
261                   if (!exhdr->ext_hdr.sp[i].numbytes)
262                     break;
263                   sparsearray[i + ind].offset =
264                     from_oct (1 + 12, exhdr->ext_hdr.sp[i].offset);
265                   sparsearray[i + ind].numbytes =
266                     from_oct (1 + 12, exhdr->ext_hdr.sp[i].numbytes);
267                 }
268               if (!exhdr->ext_hdr.isextended)
269                 break;
270               else
271                 {
272                   ind += SPARSE_EXT_HDR;
273                   userec (exhdr);
274                 }
275             }
276           userec (exhdr);
277         }
278
279       /* FALL THRU */
280     case LF_OLDNORMAL:
281     case LF_NORMAL:
282     case LF_CONTIG:
283       /*
284                   * Appears to be a file.
285                   * See if it's really a directory.
286                   */
287       namelen = strlen (skipcrud + current_file_name) - 1;
288       if (current_file_name[skipcrud + namelen] == '/')
289         goto really_dir;
290
291       /* FIXME, deal with protection issues */
292     again_file:
293       openflag = (f_keep ?
294                   O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_EXCL :
295                   O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_TRUNC)
296         | ((head->header.linkflag == LF_SPARSE) ? 0 : O_APPEND);
297       /*
298                           * JK - The last | is a kludge to solve the problem
299                           * the O_APPEND flag  causes with files we are
300                           * trying to make sparse:  when a file is opened
301                           * with O_APPEND, it writes  to the last place
302                           * that something was written, thereby ignoring
303                           * any lseeks that we have done.  We add this
304                           * extra condition to make it able to lseek when
305                           * a file is sparse, i.e., we don't open the new
306                           * file with this flag.  (Grump -- this bug caused
307                           * me to waste a good deal of time, I might add)
308                           */
309
310       if (f_exstdout)
311         {
312           fd = 1;
313           goto extract_file;
314         }
315 #ifdef O_CTG
316       /*
317                   * Contiguous files (on the Masscomp) have to specify
318                   * the size in the open call that creates them.
319                   */
320       if (head->header.linkflag == LF_CONTIG)
321         fd = open ((longname ? longname : head->header.name)
322                    + skipcrud,
323                    openflag | O_CTG,
324                    hstat.st_mode, hstat.st_size);
325       else
326 #endif
327         {
328 #ifdef NO_OPEN3
329           /*
330                           * On raw V7 we won't let them specify -k (f_keep), but
331                           * we just bull ahead and create the files.
332                           */
333           fd = creat ((longname
334                        ? longname
335                        : head->header.name) + skipcrud,
336                       hstat.st_mode);
337 #else
338           /*
339                           * With 3-arg open(), we can do this up right.
340                           */
341           fd = open (skipcrud + current_file_name,
342                      openflag, hstat.st_mode);
343 #endif
344         }
345
346       if (fd < 0)
347         {
348           if (make_dirs (skipcrud + current_file_name))
349             goto again_file;
350           msg_perror ("Could not create file %s",
351                       skipcrud + current_file_name);
352           if (head->header.isextended)
353             skip_extended_headers ();
354           skip_file ((long) hstat.st_size);
355           goto quit;
356         }
357
358     extract_file:
359       if (head->header.linkflag == LF_SPARSE)
360         {
361           char *name;
362           int namelen;
363
364           /*
365                           * Kludge alert.  NAME is assigned to header.name
366                           * because during the extraction, the space that
367                           * contains the header will get scribbled on, and
368                           * the name will get munged, so any error messages
369                           * that happen to contain the filename will look
370                           * REAL interesting unless we do this.
371                           */
372           namelen = strlen (skipcrud + current_file_name);
373           name = (char *) malloc ((sizeof (char)) * namelen);
374           bcopy (skipcrud + current_file_name, name, namelen);
375           size = hstat.st_size;
376           extract_sparse_file (fd, &size, hstat.st_size, name);
377         }
378       else
379         for (size = hstat.st_size;
380              size > 0;
381              size -= written)
382           {
383
384             /*                  long    offset,
385                                  numbytes;*/
386
387             if (f_multivol)
388               {
389                 save_name = current_file_name;
390                 save_totsize = hstat.st_size;
391                 save_sizeleft = size;
392               }
393
394             /*
395                           * Locate data, determine max length
396                           * writeable, write it, record that
397                           * we have used the data, then check
398                           * if the write worked.
399                           */
400             data = findrec ()->charptr;
401             if (data == NULL)
402               {                 /* Check it... */
403                 msg ("Unexpected EOF on archive file");
404                 break;
405               }
406             /*
407                           * JK - If the file is sparse, use the sparsearray
408                           * that we created before to lseek into the new
409                           * file the proper amount, and to see how many
410                           * bytes we want to write at that position.
411                           */
412             /*                  if (head->header.linkflag == LF_SPARSE) {
413                                  off_t pos;
414
415                                  pos = lseek(fd, (off_t) sparsearray[sparse_ind].offset, 0);
416                                  printf("%d at %d\n", (int) pos, sparse_ind);
417                                  written = sparsearray[sparse_ind++].numbytes;
418                          } else*/
419             written = endofrecs ()->charptr - data;
420             if (written > size)
421               written = size;
422             errno = 0;
423             check = write (fd, data, written);
424             /*
425                           * The following is in violation of strict
426                           * typing, since the arg to userec
427                           * should be a struct rec *.  FIXME.
428                           */
429             userec ((union record *) (data + written - 1));
430             if (check == written)
431               continue;
432             /*
433                           * Error in writing to file.
434                           * Print it, skip to next file in archive.
435                           */
436             if (check < 0)
437               msg_perror ("couldn't write to file %s",
438                           skipcrud + current_file_name);
439             else
440               msg ("could only write %d of %d bytes to file %s",
441                    written, check, skipcrud + current_file_name);
442             skip_file ((long) (size - written));
443             break;              /* Still do the close, mod time, chmod, etc */
444           }
445
446       if (f_multivol)
447         save_name = 0;
448
449       /* If writing to stdout, don't try to do anything
450                             to the filename; it doesn't exist, or we don't
451                             want to touch it anyway */
452       if (f_exstdout)
453         break;
454
455       /*                if (head->header.isextended) {
456                          register union record *exhdr;
457                          register int i;
458
459                          for (i = 0; i < 21; i++) {
460                                  long offset;
461
462                                  if (!exhdr->ext_hdr.sp[i].numbytes)
463                                          break;
464                                  offset = from_oct(1+12,
465                                                  exhdr->ext_hdr.sp[i].offset);
466                                  written = from_oct(1+12,
467                                                  exhdr->ext_hdr.sp[i].numbytes);
468                                  lseek(fd, offset, 0);
469                                  check = write(fd, data, written);
470                                  if (check == written) continue;
471
472                          }
473
474
475                  }*/
476       check = close (fd);
477       if (check < 0)
478         {
479           msg_perror ("Error while closing %s",
480                       skipcrud + current_file_name);
481         }
482
483
484     set_filestat:
485
486       /*
487                   * If we are root, set the owner and group of the extracted
488                   * file.  This does what is wanted both on real Unix and on
489                   * System V.  If we are running as a user, we extract as that
490                   * user; if running as root, we extract as the original owner.
491                   */
492       if (we_are_root || f_do_chown)
493         {
494           if (chown (skipcrud + current_file_name,
495                      hstat.st_uid, hstat.st_gid) < 0)
496             {
497               msg_perror ("cannot chown file %s to uid %d gid %d",
498                           skipcrud + current_file_name,
499                           hstat.st_uid, hstat.st_gid);
500             }
501         }
502
503       /*
504                   * Set the modified time of the file.
505                   *
506                   * Note that we set the accessed time to "now", which
507                   * is really "the time we started extracting files".
508                   * unless f_gnudump is used, in which case .st_atime is used
509                   */
510       if (!f_modified)
511         {
512           /* fixme if f_gnudump should set ctime too, but how? */
513           if (f_gnudump)
514             acc_upd_times.actime = hstat.st_atime;
515           else
516             acc_upd_times.actime = now; /* Accessed now */
517           acc_upd_times.modtime = hstat.st_mtime;       /* Mod'd */
518           if (utime (skipcrud + current_file_name,
519                      &acc_upd_times) < 0)
520             {
521               msg_perror ("couldn't change access and modification times of %s", skipcrud + current_file_name);
522             }
523         }
524       /* We do the utime before the chmod because some versions of
525                    utime are broken and trash the modes of the file.  Since
526                    we then change the mode anyway, we don't care. . . */
527
528       /*
529                  * If '-k' is not set, open() or creat() could have saved
530                  * the permission bits from a previously created file,
531                  * ignoring the ones we specified.
532                  * Even if -k is set, if the file has abnormal
533                  * mode bits, we must chmod since writing or chown() has
534                  * probably reset them.
535                  *
536                  * If -k is set, we know *we* created this file, so the mode
537                  * bits were set by our open().   If the file is "normal", we
538                  * skip the chmod.  This works because we did umask(0) if -p
539                  * is set, so umask will have left the specified mode alone.
540                  */
541       if ((!f_keep)
542           || (hstat.st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
543         {
544           if (chmod (skipcrud + current_file_name,
545                      notumask & (int) hstat.st_mode) < 0)
546             {
547               msg_perror ("cannot change mode of file %s to %ld",
548                           skipcrud + current_file_name,
549                           notumask & (int) hstat.st_mode);
550             }
551         }
552
553     quit:
554       break;
555
556     case LF_LINK:
557     again_link:
558       {
559         struct stat st1, st2;
560
561         check = link (current_link_name, skipcrud + current_file_name);
562
563         if (check == 0)
564           break;
565         if (make_dirs (skipcrud + current_file_name))
566           goto again_link;
567         if (f_gnudump && errno == EEXIST)
568           break;
569         if (stat (current_link_name, &st1) == 0
570             && stat (current_file_name + skipcrud, &st2) == 0
571             && st1.st_dev == st2.st_dev
572             && st1.st_ino == st2.st_ino)
573           break;
574         msg_perror ("Could not link %s to %s",
575                     skipcrud + current_file_name,
576                     current_link_name);
577       }
578       break;
579
580 #ifdef S_ISLNK
581     case LF_SYMLINK:
582     again_symlink:
583       check = symlink (current_link_name,
584                        skipcrud + current_file_name);
585       /* FIXME, don't worry uid, gid, etc... */
586       if (check == 0)
587         break;
588       if (make_dirs (current_file_name + skipcrud))
589         goto again_symlink;
590       msg_perror ("Could not create symlink to %s",
591                   current_link_name);
592       break;
593 #endif
594
595 #ifdef S_IFCHR
596     case LF_CHR:
597       hstat.st_mode |= S_IFCHR;
598       goto make_node;
599 #endif
600
601 #ifdef S_IFBLK
602     case LF_BLK:
603       hstat.st_mode |= S_IFBLK;
604 #endif
605 #if defined(S_IFCHR) || defined(S_IFBLK)
606     make_node:
607       check = mknod (current_file_name + skipcrud,
608                      (int) hstat.st_mode, (int) hstat.st_rdev);
609       if (check != 0)
610         {
611           if (make_dirs (skipcrud + current_file_name))
612             goto make_node;
613           msg_perror ("Could not make %s",
614                       current_file_name + skipcrud);
615           break;
616         };
617       goto set_filestat;
618 #endif
619
620 #ifdef S_ISFIFO
621       /* If local system doesn't support FIFOs, use default case */
622     case LF_FIFO:
623     make_fifo:
624       check = mkfifo (current_file_name + skipcrud,
625                       (int) hstat.st_mode);
626       if (check != 0)
627         {
628           if (make_dirs (current_file_name + skipcrud))
629             goto make_fifo;
630           msg_perror ("Could not make %s",
631                       skipcrud + current_file_name);
632           break;
633         };
634       goto set_filestat;
635 #endif
636
637     case LF_DIR:
638     case LF_DUMPDIR:
639       namelen = strlen (current_file_name) + skipcrud - 1;
640     really_dir:
641       /* Check for trailing /, and zap as many as we find. */
642       while (namelen
643              && current_file_name[skipcrud + namelen] == '/')
644         current_file_name[skipcrud + namelen--] = '\0';
645       if (f_gnudump)
646         {                       /* Read the entry and delete files
647                                            that aren't listed in the archive */
648           gnu_restore (skipcrud);
649
650         }
651       else if (head->header.linkflag == LF_DUMPDIR)
652         skip_file ((long) (hstat.st_size));
653
654
655     again_dir:
656       check = mkdir (skipcrud + current_file_name,
657                      (we_are_root ? 0 : 0300) | (int) hstat.st_mode);
658       if (check != 0)
659         {
660           struct stat st1;
661
662           if (make_dirs (skipcrud + current_file_name))
663             goto again_dir;
664           /* If we're trying to create '.', let it be. */
665           if (current_file_name[skipcrud + namelen] == '.' &&
666               (namelen == 0 ||
667                current_file_name[skipcrud + namelen - 1] == '/'))
668             goto check_perms;
669           if (errno == EEXIST
670               && stat (skipcrud + current_file_name, &st1) == 0
671               && (S_ISDIR (st1.st_mode)))
672             break;
673           msg_perror ("Could not create directory %s", skipcrud + current_file_name);
674           break;
675         }
676
677     check_perms:
678       if (!we_are_root && 0300 != (0300 & (int) hstat.st_mode))
679         {
680           hstat.st_mode |= 0300;
681           msg ("Added write and execute permission to directory %s",
682                skipcrud + current_file_name);
683         }
684
685       if (f_modified)
686         goto set_filestat;
687       tmp = (struct saved_dir_info *) malloc (sizeof (struct saved_dir_info));
688       tmp->path = malloc (strlen (skipcrud + current_file_name) + 1);
689       strcpy (tmp->path, skipcrud + current_file_name);
690       tmp->mode = hstat.st_mode;
691       tmp->atime = hstat.st_atime;
692       tmp->mtime = hstat.st_mtime;
693       tmp->next = saved_dir_info_head;
694       saved_dir_info_head = tmp;
695     case LF_VOLHDR:
696       if (f_verbose)
697         {
698           printf ("Reading %s\n", current_file_name);
699         }
700       break;
701
702     case LF_NAMES:
703       extract_mangle (head);
704       break;
705
706     case LF_MULTIVOL:
707       msg ("Can't extract '%s'--file is continued from another volume\n", current_file_name);
708       skip_file ((long) hstat.st_size);
709       break;
710
711     case LF_LONGNAME:
712     case LF_LONGLINK:
713       msg ("Visible long name error\n");
714       skip_file ((long) hstat.st_size);
715       break;
716     }
717
718   /* We don't need to save it any longer. */
719   saverec ((union record **) 0);/* Unsave it */
720 }
721
722 /*
723  * After a file/link/symlink/dir creation has failed, see if
724  * it's because some required directory was not present, and if
725  * so, create all required dirs.
726  */
727 int
728 make_dirs (pathname)
729      char *pathname;
730 {
731   char *p;                      /* Points into path */
732   int madeone = 0;              /* Did we do anything yet? */
733   int save_errno = errno;       /* Remember caller's errno */
734   int check;
735
736   if (errno != ENOENT)
737     return 0;                   /* Not our problem */
738
739   for (p = index (pathname, '/'); p != NULL; p = index (p + 1, '/'))
740     {
741       /* Avoid mkdir of empty string, if leading or double '/' */
742       if (p == pathname || p[-1] == '/')
743         continue;
744       /* Avoid mkdir where last part of path is '.' */
745       if (p[-1] == '.' && (p == pathname + 1 || p[-2] == '/'))
746         continue;
747       *p = 0;                   /* Truncate the path there */
748       check = mkdir (pathname, 0777);   /* Try to create it as a dir */
749       if (check == 0)
750         {
751           /* Fix ownership */
752           if (we_are_root)
753             {
754               if (chown (pathname, hstat.st_uid,
755                          hstat.st_gid) < 0)
756                 {
757                   msg_perror ("cannot change owner of %s to uid %d gid %d", pathname, hstat.st_uid, hstat.st_gid);
758                 }
759             }
760           pr_mkdir (pathname, p - pathname, notumask & 0777);
761           madeone++;            /* Remember if we made one */
762           *p = '/';
763           continue;
764         }
765       *p = '/';
766       if (errno == EEXIST)      /* Directory already exists */
767         continue;
768       /*
769                  * Some other error in the mkdir.  We return to the caller.
770                  */
771       break;
772     }
773
774   errno = save_errno;           /* Restore caller's errno */
775   return madeone;               /* Tell them to retry if we made one */
776 }
777
778 void
779 extract_sparse_file (fd, sizeleft, totalsize, name)
780      int fd;
781      long *sizeleft, totalsize;
782      char *name;
783 {
784   /*    register char   *data;*/
785   union record *datarec;
786   int sparse_ind = 0;
787   int written, count;
788
789   /* assuming sizeleft is initially totalsize */
790
791
792   while (*sizeleft > 0)
793     {
794       datarec = findrec ();
795       if (datarec == NULL)
796         {
797           msg ("Unexpected EOF on archive file");
798           return;
799         }
800       lseek (fd, sparsearray[sparse_ind].offset, 0);
801       written = sparsearray[sparse_ind++].numbytes;
802       while (written > RECORDSIZE)
803         {
804           count = write (fd, datarec->charptr, RECORDSIZE);
805           if (count < 0)
806             msg_perror ("couldn't write to file %s", name);
807           written -= count;
808           *sizeleft -= count;
809           userec (datarec);
810           datarec = findrec ();
811         }
812
813       count = write (fd, datarec->charptr, written);
814
815       if (count < 0)
816         {
817           msg_perror ("couldn't write to file %s", name);
818         }
819       else if (count != written)
820         {
821           msg ("could only write %d of %d bytes to file %s", totalsize - *sizeleft, totalsize, name);
822           skip_file ((long) (*sizeleft));
823         }
824
825       written -= count;
826       *sizeleft -= count;
827       userec (datarec);
828     }
829   free (sparsearray);
830   /*    if (end_nulls) {
831                 register int i;
832
833                 printf("%d\n", (int) end_nulls);
834                 for (i = 0; i < end_nulls; i++)
835                         write(fd, "\000", 1);
836         }*/
837   userec (datarec);
838 }
839
840 /* Set back the utime and mode for all the extracted directories. */
841 void 
842 restore_saved_dir_info ()
843 {
844   struct utimbuf acc_upd_times;
845   struct saved_dir_info *tmp;
846
847   while (saved_dir_info_head != NULL)
848     {
849       /* fixme if f_gnudump should set ctime too, but how? */
850       if (f_gnudump)
851         acc_upd_times.actime = saved_dir_info_head->atime;
852       else
853         acc_upd_times.actime = now;     /* Accessed now */
854       acc_upd_times.modtime = saved_dir_info_head->mtime;       /* Mod'd */
855       if (utime (saved_dir_info_head->path, &acc_upd_times) < 0)
856         {
857           msg_perror ("couldn't change access and modification times of %s",
858                       saved_dir_info_head->path);
859         }
860       if ((!f_keep) || (saved_dir_info_head->mode & (S_ISUID | S_ISGID | S_ISVTX)))
861         {
862           if (chmod (saved_dir_info_head->path,
863                      notumask & saved_dir_info_head->mode) < 0)
864             {
865               msg_perror ("cannot change mode of file %s to %ld",
866                           saved_dir_info_head->path,
867                           notumask & saved_dir_info_head->mode);
868             }
869         }
870       saved_dir_info_head = saved_dir_info_head->next;
871     }
872 }