home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / tar-1.11.8-src.tgz / tar.out / fsf / tar / src / extract.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  24KB  |  881 lines

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