Example #1
0
int
is_tar_header (char *buf)
{
  struct tar_header *tar_hdr = (struct tar_header *) buf;
  unsigned long chksum;

  chksum = FROM_OCTAL (tar_hdr->chksum);

  if (chksum != tar_checksum (tar_hdr))
    return 0;

  /* GNU tar 1.10 and previous set the magic field to be "ustar " instead
     of "ustar\0".  Only look at the first 5 characters of the magic
     field so we can recognize old GNU tar ustar archives.  */
  if (!strncmp (tar_hdr->magic, TMAGIC, TMAGLEN - 1))
      return 2;
  return 1;
}
Example #2
0
int  IsTARFile( LPDFSTR lpdf, LPTSTR lpf, PBYTE pb, DWORD dwmax )
{
   int  bRet = 0;
   LPTSTR   lpb = &gcOutBuf[0];  // [16K]
   PTAR  pt = (PTAR)pb;
   PUSTAR put = (PUSTAR)pb;
   char * pv = (char *)lpdf->df_pVoid;
   size_t off, count, boff, fsz, remains, len, culen;
   struct posix_header * pph = (struct posix_header *)lpdf->df_pVoid;
   int i;

   iMaxNameLen = 0;
   iMaxFileSize = 0;
   iMinFileSize = 0x7fffffff;
   iFileCount = 0;
   iDirCount = 0;
   if(!pv || !pb)
      return bRet;

   tar_stat_destroy(&current_stat_info);
   current_header = (union block *)pph;
   rdhdr = tar_checksum ((union block *)pph, TRUE);
   current_format = -1;
   decode_header_format ((union block *)pph, &current_stat_info, &current_format, 0);
   if( VERB5 )
   {
      sprtf( "%s: Format appears to be [%s] (%d)..."MEOR,
         get_header_stg( rdhdr ),
         get_format_stg(current_format),
         current_format );
   }

   switch(current_format)
   {
   case V7_FORMAT:
      break;
   case OLDGNU_FORMAT:
      poldgnu_header = (struct oldgnu_header *)pph;
      break;
   case USTAR_FORMAT:
      break;
   case POSIX_FORMAT:
      pheader = (struct posix_header * )pph;
      break;
   case STAR_FORMAT:
      pstar_header = (struct star_header *)pph; 
      break;
   case GNU_FORMAT:
      break;
   default:
      break;
   }

   if(( _strnicmp(put->ustar, "ustar", 5) == 0  )||
      ( rdhdr == HEADER_SUCCESS ) ) {
      off = 1;
      count = 0;
      while(off)
      {
         boff = count * BLOCKSIZE;
         pph = (struct posix_header *) &pv[boff];
         if( (boff + BLOCKSIZE) > lpdf->dwmax )
         {
            sprtf( "ERROR: Offset %d GREATER THAN max %d ..."MEOR,
               (boff + BLOCKSIZE), lpdf->dwmax );
            return 0;
         }
         off = 0;
         fsz = 0;
         i = collect_octal_size( lpb, pph, &fsz, 0 );
         if( i == 1 )
         {
            if(( pph->typeflag == REGTYPE ) || ( pph->typeflag == AREGTYPE ))
            {
               if(fsz > iMaxFileSize)
                  iMaxFileSize = fsz;
               if(fsz < iMinFileSize)
                  iMinFileSize = fsz;
            }
         }
         off = collect_prefix_name( lpb, pph );
         if( off ) {
            if( off > iMaxNameLen )
               iMaxNameLen = off;
            //sprtf( "Entry [%s] is %s ... size %d"MEOR, lpb,
            //   get_type_string(pph->typeflag),
            //   fsz );
            switch(pph->typeflag)
            {
            case REGTYPE:
            case AREGTYPE:
               iFileCount++;
               remains = fsz;
               while(remains)
               {
                  count++;
                  boff = count * BLOCKSIZE;
                  if( (boff + BLOCKSIZE) > lpdf->dwmax )
                  {
                     sprtf( "ERROR: Offset %d GREATER THAN max %d ..."MEOR,
                        (boff + BLOCKSIZE), lpdf->dwmax );
                     return 0;
                  }
                  if(remains > BLOCKSIZE)
                     len = BLOCKSIZE;
                  else
                     len = remains;
                  culen = 0;
                  pph = (struct posix_header *) &pv[boff];
                  if(remains > BLOCKSIZE)
                     remains -= BLOCKSIZE;
                  else
                     remains = 0;
               }
               break;
            case DIRTYPE:  // , "directory" },     //  '5'		/* directory */
               iDirCount++;            
               break;
            case LNKTYPE:  // , "link" },
            case SYMTYPE:  //, "reserved" },
            case CHRTYPE:  // , "character special" },
            case BLKTYPE:  //, "block special" }, //  '4'		/* block special */
            case FIFOTYPE: //, "FIFO special" }, // '6'		/* FIFO special */
            case CONTTYPE: //, "reserved" },     // '7'		/* reserved */
               break;
            case XHDTYPE:  //, "extended header" }, //  'x'   /* Extended header referring to the next file in the archive */
               // should bump to NEXT, but this is only a CHECK of TAR, not decode yet

               break;
            case XGLTYPE:  //, "global header" }, //  'g'            /* Global extended header */
               break;
            default:
               //sprtf("WARNING: Uncased type %c!!!"MEOR, pph->typeflag);
               break;
            }
         } else {
            break;
         }
         count++;
      }
      count++;
      boff = count * BLOCKSIZE;
      if( (boff + BLOCKSIZE) > lpdf->dwmax )
      {
         sprtf( "ERROR: Offset %d GREATER THAN max %d ..."MEOR,
            (boff + BLOCKSIZE), lpdf->dwmax );
         return 0;
      }
      if(VERB5) {
         remains = (lpdf->dwmax - (boff + BLOCKSIZE));
         strcpy(lpb, (remains == 0 ? "perfect" : "remainder " ));
         if(remains) sprintf(EndBuf(lpb)," %d", remains );
         sprtf( "Tested to offset %d of %d ... %s"MEOR,
            (boff + BLOCKSIZE), lpdf->dwmax, lpb );
         if( remains && VERB9 )
         {
            while(remains)
            {
               boff = count * BLOCKSIZE;
               if(remains > BLOCKSIZE)
                  len = BLOCKSIZE;
               else
                  len = remains;
               culen = 0;
               pph = (struct posix_header *) &pv[boff];
               if(remains > BLOCKSIZE)
                  remains -= BLOCKSIZE;
               else
                  remains = 0;
               count++;
            }
         }
      }
      return 2;
   } else {
      // NOT ustar 
      // what to do ...
   }

   return bRet;
}
Example #3
0
BOOL  DumpTAR_FAILED( LPDFSTR lpdf )
{
   BOOL  bRet = FALSE;
   LPTSTR   lpb = &gcOutBuf[0];  // [16K]
   LPTSTR   lpb2 = &gcOutBuf2[0];  // [16K]
   char * pv = (char *)lpdf->df_pVoid;
   struct posix_header * pph = (struct posix_header *)lpdf->df_pVoid;
   char * cp;
   size_t   off, boff, count, fsz, remains, len, hlen, culen;
   int   i;
   char c;
   size_t maxcnt = iFileCount + iDirCount;
   size_t entry = 0;
   enum read_header h;
   struct tar_stat_info * info = &current_stat_info;
   DWORD dwm = lpdf->dwmax;
   union block * p;
   if( !pph )
      return bRet;

   iMaxFileSize = 0;
   iMinFileSize = 0x7fffffff;
   current_block = (union block *)pv;
   dwm = lpdf->dwmax;
   p = current_block;
   while(dwm)
   {
      record_end = p;
      p++;
      if(dwm >= BLOCKSIZE)
      {
         dwm -= BLOCKSIZE;
         if(dwm == 0)
            record_end = p;
      }
      else
         dwm = 0;
   }

   if(( _strnicmp(pph->magic, TMAGIC, 5) == 0 )||
      ( rdhdr == HEADER_SUCCESS ) ){
      // we have a USTAR format
      off = 1;
      count = 0;
      sprtf( "TAR [%s] is [%s] format ..."MEOR,
         lpdf->fn,
         get_format_stg(current_format) );
      while(off)
      {
         entry++;
         boff = count * BLOCKSIZE;
         pph = (struct posix_header *) &pv[boff];
         if( (boff + BLOCKSIZE) > lpdf->dwmax )
         {
            sprtf( "WARNING: DATA EXPIRED BEFORE ZERO BLOCK!"MEOR );
            break;
         }
         tar_stat_destroy(info);
         current_header = (union block *)pph;
         h = tar_checksum ((union block *)pph, TRUE);
         form = -1;
         decode_header ((union block *)pph, info, &form, 0);
         //      if (header->header.typeflag == LNKTYPE)
         if( pph->typeflag == LNKTYPE )
            info->stat.st_size = 0;	/* links 0 size on tape */
         else
            info->stat.st_size = OFF_FROM_HEADER (pph->size);
         fsz = (size_t)info->stat.st_size;
         if( VERB5 )
         {
            cp = (char *)pph;
            sprtf( "%s: form [%s](%d): type [%s]: size %9d; offset %#08X; time %s"MEOR,
               get_header_stg( h ),
               get_format_stg(form),
               form,
               get_type_string( pph->typeflag),
               info->stat.st_size,
               (cp - pv),
               tartime( info->mtime, 0 ));
         }
         // else if (header->header.typeflag == XHDTYPE
		   // || header->header.typeflag == SOLARIS_XHDTYPE)
         if(( h == HEADER_SUCCESS )&&
            (( pph->typeflag == XHDTYPE )||
             ( pph->typeflag == SOLARIS_XHDTYPE )))
         {
            // we need to READ the xheader ...
            struct posix_header * pph_save = pph;
            fsz = (size_t)info->stat.st_size;
            len = 1;
            xheader_read (&info->xhdr, (union block *)pph, (size_t)fsz);
            if( VERB9 )
               sprtf( "Skipping %d extended header blocks ...\n", len );
            boff = ((count + len) * BLOCKSIZE);
            pph = (struct posix_header *)&pv[boff];
            if( (boff + BLOCKSIZE) > lpdf->dwmax )
            {
               sprtf( "WARNING: DATA EXPIRED BEFORE ZERO BLOCK!"MEOR );
               pph = pph_save;
               break;
            }
            tar_stat_destroy(info);
            pph = (struct posix_header *)current_block; // move up to this block
            current_header = (union block *)pph;
            h = tar_checksum ((union block *)pph, TRUE);
            form = -1;
            decode_header ((union block *)pph, info, &form, 0);
            if( pph->typeflag == LNKTYPE )
               info->stat.st_size = 0;	/* links 0 size on tape */
            else
               info->stat.st_size = OFF_FROM_HEADER (pph->size);
            fsz = (size_t)info->stat.st_size;
            if( h == HEADER_SUCCESS ) {
               XHDTYPE_count++;
               if( VERB5 )
               {
                  cp = (char *)pph;
                  sprtf( "%s: form [%s](%d): type [%s]: size %9d; offset %#08X; time %s"MEOR,
                     get_header_stg( h ),
                     get_format_stg(form),
                     form,
                     get_type_string( pph->typeflag),
                     info->stat.st_size,
                     (cp - pv),
                     tartime( info->mtime, 0 ));
               }
               count += len;
            } else {
               pph = pph_save;
               tar_stat_destroy(info);
               current_header = (union block *)pph;
               h = tar_checksum ((union block *)pph, TRUE);
               form = -1;
               decode_header ((union block *)pph, info, &form, 0);
            }
         }

         fsz = 0;
         i = collect_octal_size( lpb, pph, &fsz, 1 );
         off = collect_prefix_name( lpb, pph );
         if( off ) {
            // we GOT a NAME
            sprtf( "%5d %-50s %s %10d %s"MEOR,
               entry,
               lpb,
               get_type_string(pph->typeflag),
               fsz,
               tartime( info->mtime, 0 ));
            // gather counts
            switch(pph->typeflag)
            {
            case REGTYPE:
            case AREGTYPE:
               REGTYPE_count++;
               if( fsz > iMaxFileSize )
                  iMaxFileSize = fsz;
               if( fsz < iMinFileSize )
                  iMinFileSize = fsz;
               remains = fsz;
               while(remains)
               {
                  count++;
                  boff = count * BLOCKSIZE;
                  if(remains > BLOCKSIZE)
                     len = BLOCKSIZE;
                  else
                     len = remains;
                  culen = 0;
                  if( VERB9 && bExtraDebug )
                  {
                     while( len )
                     {
                        if(len > 16)
                           hlen = 16;
                        else
                           hlen = len;
                        *lpb = 0;
                        GetHEXString( lpb, &pv[boff+culen], hlen, pv, FALSE );
                        sprtf( "%s"MEOR, lpb );
                        len -= hlen;
                        culen += hlen;
                     }
                  }
                  pph = (struct posix_header *) &pv[boff];
                  if(remains > BLOCKSIZE)
                     remains -= BLOCKSIZE;
                  else
                     remains = 0;
               }
               break;
            case LNKTYPE:  // , "link" },
               LNKTYPE_count++;
               break;
            case SYMTYPE:  //, "reserved" },
               SYMTYPE_count++;
               break;
            case CHRTYPE:  // , "character special" },
               CHRTYPE_count++;
               break;
            case BLKTYPE:  //, "block special" }, //  '4'		/* block special */
               BLKTYPE_count++;
               break;
            case DIRTYPE:  // , "directory" },     //  '5'		/* directory */
               DIRTYPE_count++;
               break;
            case FIFOTYPE: //, "FIFO special" }, // '6'		/* FIFO special */
               FIFOTYPE_count++;
               break;
            case CONTTYPE: //, "reserved" },     // '7'		/* reserved */
               CONTTYPE_count++;
               break;
            case XHDTYPE:  //, "extended header" }, //  'x'   /* Extended header referring to the next file in the archive */
               XHDTYPE_count++;
               break;
            case XGLTYPE:  //, "global header" }, //  'g'            /* Global extended header */
               XGLTYPE_count++;
               break;
            default:
               default_count++;
               sprtf("WARNING: Uncased type %c!!!"MEOR, pph->typeflag);
               break;
            }
         }
         count++;
      }  // while ...

      if( max_warn_count < warn_count )
      {
         sprtf( "WARNING: Plus another [%d] OUT OF OCTAL RANGE!!!"MEOR,
            warn_count - max_warn_count );
      }

      // fell out because of a BLANK block
      sprtf( "Processed %d entries", maxcnt );
      if( REGTYPE_count ) {
         // case AREGTYPE: counted with above
         sprtf( ", %d file%s (min %d, max %d)",
            REGTYPE_count,
            ((REGTYPE_count == 1) ? "" : "s"),
            iMinFileSize,
            iMaxFileSize );
      }
      if( LNKTYPE_count )
         sprtf( ", %d link%s", LNKTYPE_count, ((LNKTYPE_count == 1) ? "" : "s") );
      if( SYMTYPE_count )
         sprtf( ", %d sym%s", SYMTYPE_count, ((SYMTYPE_count == 1) ? "" : "s") );
      if( CHRTYPE_count )
         sprtf( ", %d char%s", CHRTYPE_count, ((CHRTYPE_count == 1) ? "" : "s") );
      if( BLKTYPE_count )
         sprtf( ", %d block%s", BLKTYPE_count, ((BLKTYPE_count == 1) ? "" : "s") );
      if( DIRTYPE_count )
         sprtf( ", %d dir%s", DIRTYPE_count, ((DIRTYPE_count == 1) ? "" : "s") );
      if( FIFOTYPE_count )
         sprtf( ", %d fifo%s", FIFOTYPE_count, ((FIFOTYPE_count == 1) ? "" : "s") );
      if( CONTTYPE_count )
         sprtf( ", %d cont%s", CONTTYPE_count, ((CONTTYPE_count == 1) ? "" : "s") );
      if( XHDTYPE_count )
         sprtf( ", %d xhdr%s", XHDTYPE_count, ((XHDTYPE_count == 1) ? "" : "s") );
      if( XGLTYPE_count )
         sprtf( ", %d xgl%s", XGLTYPE_count, ((XGLTYPE_count == 1) ? "" : "s") );
      if( default_count )
         sprtf( ", %d default%s", default_count, ((default_count == 1) ? "" : "s") );
      sprtf( " (blocks %d)"MEOR,
         count );

      count++;
      boff = count * BLOCKSIZE;
      remains = (lpdf->dwmax - (boff + BLOCKSIZE));
      strcpy(lpb, (remains == 0 ? "perfect" : "remainder " ));
      if(remains) sprintf(EndBuf(lpb)," %d", remains );
      if(remains > 0)
      {
         off = 0;
         boff = count * BLOCKSIZE;
         if( VERB )
            sprtf( "Reached offset %d of %d ... %s"MEOR,
            (boff + BLOCKSIZE), lpdf->dwmax, lpb );
         while(remains > 0)
         {
            if(remains > BLOCKSIZE)
               len = BLOCKSIZE;
            else
               len = remains;
            culen = 0;
            remains -= len;
            while( len )
            {
               if(len > 16)
                  hlen = 16;
               else
                  hlen = len;
               for( i = 0; i < (int)hlen; i++ )
               {
                  c = pv[boff+culen+i];
                  if(c)
                     break;
               }
               if(c) {
                  if(VERB5)
                  {
                     *lpb = 0;
                     GetHEXString( lpb, &pv[boff+culen], hlen, pv, FALSE );
                     sprtf( "%s"MEOR, lpb );
                  }
                  off++;
               }
               len -= hlen;
               culen += hlen;
            }
            count++;
         }
         // done the remainder
         if( off == 0 ) {
            // NO HEX OUTPUT
            sprtf( "But it was ALL zeros ... (to %d)"MEOR, ((count+1) * BLOCKSIZE) );
         }
      }
      bRet = TRUE;
   }

   return bRet;
}
Example #4
0
void
read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des)
{
  long bytes_skipped = 0;
  int warned = false;
  union tar_record tar_rec;
  struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
  uid_t *uidp;
  gid_t *gidp;

  tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);

  /* Check for a block of 0's.  */
  if (null_block ((long *) &tar_rec, TARRECORDSIZE))
    {
#if 0
      /* Found one block of 512 0's.  If the next block is also all 0's
	 then this is the end of the archive.  If not, assume the
	 previous block was all corruption and continue reading
	 the archive.  */
      /* Commented out because GNU tar sometimes creates archives with
	 only one block of 0's at the end.  This happened for the
	 cpio 2.0 distribution!  */
      tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
      if (null_block ((long *) &tar_rec, TARRECORDSIZE))
#endif
	{
	  file_hdr->c_name = CPIO_TRAILER_NAME;
	  return;
	}
#if 0
      bytes_skipped = TARRECORDSIZE;
#endif
    }

  while (1)
    {
      file_hdr->c_chksum = FROM_OCTAL (tar_hdr->chksum);

      if (file_hdr->c_chksum != tar_checksum (tar_hdr))
	{
	  /* If the checksum is bad, skip 1 byte and try again.  When
	     we try again we do not look for an EOF record (all zeros),
	     because when we start skipping bytes in a corrupted archive
	     the chances are pretty good that we might stumble across
	     2 blocks of 512 zeros (that probably is not really the last
	     record) and it is better to miss the EOF and give the user
	     a "premature EOF" error than to give up too soon on a corrupted
	     archive.  */
	  if (!warned)
	    {
	      error (0, 0, _("invalid header: checksum error"));
	      warned = true;
	    }
	  memmove (&tar_rec, ((char *) &tar_rec) + 1, TARRECORDSIZE - 1);
	  tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
	  ++bytes_skipped;
	  continue;
	}

      if (archive_format != arf_ustar)
	file_hdr->c_name = stash_tar_filename (NULL, tar_hdr->name);
      else
	file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
      file_hdr->c_nlink = 1;
      file_hdr->c_mode = FROM_OCTAL (tar_hdr->mode);
      file_hdr->c_mode = file_hdr->c_mode & 07777;
  /* Debian hack: This version of cpio uses the -n flag also to extract
     tar archives using the numeric UID/GID instead of the user/group
     names in /etc/passwd and /etc/groups.  (98/10/15) -BEM */
      if (archive_format == arf_ustar && !numeric_uid
	  && (uidp = getuidbyname (tar_hdr->uname)))
	file_hdr->c_uid = *uidp;
      else
	file_hdr->c_uid = FROM_OCTAL (tar_hdr->uid);

      if (archive_format == arf_ustar && !numeric_uid
	  && (gidp = getgidbyname (tar_hdr->gname)))
	file_hdr->c_gid = *gidp;
      else
	file_hdr->c_gid = FROM_OCTAL (tar_hdr->gid);
      file_hdr->c_filesize = FROM_OCTAL (tar_hdr->size);
      file_hdr->c_mtime = FROM_OCTAL (tar_hdr->mtime);
      file_hdr->c_rdev_maj = FROM_OCTAL (tar_hdr->devmajor);
      file_hdr->c_rdev_min = FROM_OCTAL (tar_hdr->devminor);
      file_hdr->c_tar_linkname = NULL;

      switch (tar_hdr->typeflag)
	{
	case REGTYPE:
	case CONTTYPE:		/* For now, punt.  */
	default:
	  file_hdr->c_mode |= CP_IFREG;
	  break;
	case DIRTYPE:
	  file_hdr->c_mode |= CP_IFDIR;
	  break;
	case CHRTYPE:
	  file_hdr->c_mode |= CP_IFCHR;
	  /* If a POSIX tar header has a valid linkname it's always supposed
	     to set typeflag to be LNKTYPE.  System V.4 tar seems to
	     be broken, and for device files with multiple links it
	     puts the name of the link into linkname, but leaves typeflag 
	     as CHRTYPE, BLKTYPE, FIFOTYPE, etc.  */
	  file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);

	  /* Does POSIX say that the filesize must be 0 for devices?  We
	     assume so, but HPUX's POSIX tar sets it to be 1 which causes
	     us problems (when reading an archive we assume we can always
	     skip to the next file by skipping filesize bytes).  For 
	     now at least, it's easier to clear filesize for devices,
	     rather than check everywhere we skip in copyin.c.  */
	  file_hdr->c_filesize = 0;
	  break;
	case BLKTYPE:
	  file_hdr->c_mode |= CP_IFBLK;
	  file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
	  file_hdr->c_filesize = 0;
	  break;
#ifdef CP_IFIFO
	case FIFOTYPE:
	  file_hdr->c_mode |= CP_IFIFO;
	  file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
	  file_hdr->c_filesize = 0;
	  break;
#endif
	case SYMTYPE:
#ifdef CP_IFLNK
	  file_hdr->c_mode |= CP_IFLNK;
	  file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
	  file_hdr->c_filesize = 0;
	  break;
	  /* Else fall through.  */
#endif
	case LNKTYPE:
	  file_hdr->c_mode |= CP_IFREG;
	  file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
	  file_hdr->c_filesize = 0;
	  break;

	case AREGTYPE:
	  /* Old tar format; if the last char in filename is '/' then it is
	     a directory, otherwise it's a regular file.  */
	  if (file_hdr->c_name[strlen (file_hdr->c_name) - 1] == '/')
	    file_hdr->c_mode |= CP_IFDIR;
	  else
	    file_hdr->c_mode |= CP_IFREG;
	  break;
	}
      break;
    }
  if (bytes_skipped > 0)
    warn_junk_bytes (bytes_skipped);
}
Example #5
0
void
write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des)
{
  int name_len;
  union tar_record tar_rec;
  struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;

  memset (&tar_rec, 0, sizeof tar_rec);

  /* process_copy_out must ensure that file_hdr->c_name is short enough,
     or we will lose here.  */

  name_len = strlen (file_hdr->c_name);
  if (name_len <= TARNAMESIZE)
    {
      strncpy (tar_hdr->name, file_hdr->c_name, name_len);
    }
  else
    {
      /* Fit as much as we can into `name', the rest into `prefix'.  */
      int prefix_len = split_long_name (file_hdr->c_name, name_len);

      strncpy (tar_hdr->prefix, file_hdr->c_name, prefix_len);
      strncpy (tar_hdr->name, file_hdr->c_name + prefix_len + 1,
	       name_len - prefix_len - 1);
    }

  /* Ustar standard (POSIX.1-1988) requires the mode to contain only 3 octal
     digits */
  to_oct (file_hdr->c_mode & MODE_ALL, 8, tar_hdr->mode);
  to_oct (file_hdr->c_uid, 8, tar_hdr->uid);
  to_oct (file_hdr->c_gid, 8, tar_hdr->gid);
  to_oct (file_hdr->c_filesize, 12, tar_hdr->size);
  to_oct (file_hdr->c_mtime, 12, tar_hdr->mtime);

  switch (file_hdr->c_mode & CP_IFMT)
    {
    case CP_IFREG:
      if (file_hdr->c_tar_linkname)
	{
	  /* process_copy_out makes sure that c_tar_linkname is shorter
	     than TARLINKNAMESIZE.  */
	  strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
		   TARLINKNAMESIZE);
	  tar_hdr->typeflag = LNKTYPE;
	  to_oct (0, 12, tar_hdr->size);
	}
      else
	tar_hdr->typeflag = REGTYPE;
      break;
    case CP_IFDIR:
      tar_hdr->typeflag = DIRTYPE;
      break;
    case CP_IFCHR:
      tar_hdr->typeflag = CHRTYPE;
      break;
    case CP_IFBLK:
      tar_hdr->typeflag = BLKTYPE;
      break;
#ifdef CP_IFIFO
    case CP_IFIFO:
      tar_hdr->typeflag = FIFOTYPE;
      break;
#endif /* CP_IFIFO */
#ifdef CP_IFLNK
    case CP_IFLNK:
      tar_hdr->typeflag = SYMTYPE;
      /* process_copy_out makes sure that c_tar_linkname is shorter
	 than TARLINKNAMESIZE.  */
      strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
	       TARLINKNAMESIZE);
      to_oct (0, 12, tar_hdr->size);
      break;
#endif /* CP_IFLNK */
    }

  if (archive_format == arf_ustar)
    {
      char *name;

      strncpy (tar_hdr->magic, TMAGIC, TMAGLEN);
      strncpy (tar_hdr->version, TVERSION, TVERSLEN);

      name = getuser (file_hdr->c_uid);
      if (name)
	strcpy (tar_hdr->uname, name);
      name = getgroup (file_hdr->c_gid);
      if (name)
	strcpy (tar_hdr->gname, name);

      to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor);
      to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor);
    }

  to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum);

  tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE);
}
Example #6
0
ArchiveEntryNode *next_tar_entry(void)
{
    char hdr[TARHDRSIZ];
    long size, sizeb;
    ArchiveEntryNode *entry;
    URL url;
    int flen;
    int macbin_check;

    url = arc_handler.url;
    macbin_check = (arc_handler.counter == 0);

retry_read:
    if(!macbin_check)
    {
        if(url_read(url, hdr, TARHDRSIZ) != TARHDRSIZ)
            return NULL;
    }
    else
    {
        int c = url_getc(url);
        if(c == 0)
        {
            url_skip(url, 127);
            if(arc_handler.isfile)
                arc_handler.pos += 128;
            if(url_read(url, hdr, TARHDRSIZ) != TARHDRSIZ)
                return NULL;
        }
        else
        {
            hdr[0] = c;
            if(url_read(url, hdr+1, TARHDRSIZ-1) != TARHDRSIZ-1)
                return NULL;
        }
    }

    macbin_check = 0;

    if(hdr[0] == '\0')
        return NULL;
    if(!tar_checksum(hdr))
        return NULL;
    size = octal_value(hdr + 124, 12);
    flen = strlen(hdr);
    if(size == 0 && flen > 0 && hdr[flen - 1] == '/')
    {
        if(arc_handler.isfile)
            arc_handler.pos += TARHDRSIZ;
        goto retry_read;
    }

    entry = new_entry_node(hdr, flen);
    if(entry == NULL)
        return NULL;
    sizeb = (((size) + (TARBLKSIZ-1)) & ~(TARBLKSIZ-1));

    if((arc_handler.isfile) || (size > MAX_SAFE_MALLOC_SIZE))
    {
        arc_handler.pos += TARHDRSIZ;
        entry->comptype = ARCHIVEC_STORED;
        entry->compsize = entry->origsize = size;
        entry->start = arc_handler.pos;
        url_skip(url, sizeb);
        arc_handler.pos += sizeb;
    }
    else
    {
        void *data;
        long n;

        data = url_dump(url, size, &n);
        if(size != n)
        {
            if(data != NULL)
                free(data);
            free_entry_node(entry);
            return NULL;
        }
        entry->cache = arc_compress(data, size, ARC_DEFLATE_LEVEL,
                                    &entry->compsize);
        free(data);
        entry->comptype = ARCHIVEC_DEFLATED;
        entry->origsize = size;
        entry->start = 0;
        url_skip(url, sizeb - size);
    }

    return entry;
}