This is the mail archive of the cygwin-patches@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] File type auto-recognition


Attached are several new files to be added to the cinstall directory for
the auto file type recognition stuff.  Also attached is a new version of
tar.cc and tar.h -- the diffs are larger than the actual files, so I
figured it would be better just to send my new version of each file. 
And finally, there are two small diffs, to Makefile.in and install.cc,
which are very straightforward.

The tar.cc work doesn't actually represent a lot of functional change. 
But in moving to OO-ness, I renamed many functions and variables, so
lots of code lines got touched.

In doing this work, I noticed that the "tar_auto" mechanism isn't used
by any of the code.  This is pretty complicated code, so if no one has
plans to use it, all the ifdef 0'd sections I've marked should be diked
out to avoid confusing future spelunkers.  There are also several single
lines commented with a //! prefix that should also be axed.

This patch doesn't do all the nio-* refactoring that I also discussed. 
It's just a pretty version of the first patch I did.  What with recent
comments by Robert and Chuck, I figured I needed to ship _something_. 
(My day job has been a bear lately...)

Here are the changelog entries:

2001-11-06  Warren Young  <warren@etr-usa.com>

        * winsup/cinstall/Makefile.in: Add archive.o, bzdecomp.o,
        decomp.o, and gzdecomp.o

        * winsup/cinstall/tar.cc: Refactor it to be a subclass of
        Archive, and extract the gzbz mechanism.

        * winsup/cinstall/tar.h: Declare TarArchive, a new subclass
        of Archive, to contain the tar file handling functions.

        * winsup/cinstall/archive.cc: New module, contains the basic
        archive file handling mechanism.

        * winsup/cinstall/archive.h: New header, declares the Archive 
        class.

        * winsup/cinstall/decomp.cc: New module, contains the basic
        decompression mechanism.

        * winsup/cinstall/decomp.h: New header, declares the Decomp 
        class.

        * winsup/cinstall/gzdecomp.cc: New module, defines the gzip
        file decompression class.  This came from tar.cc's old gzbz
        mechanism.

        * winsup/cinstall/gzdecomp.h: New header, declares the GZDecomp 
        class.

        * winsup/cinstall/bzdecomp.cc: New module, defines the bzip
        file decompression class.  This came from tar.cc's old gzbz
        mechanism.

        * winsup/cinstall/bzdecomp.h: New header, declares the BZDecomp
        class.

        * winsup/cinstall/install.cc: Use the new Archive mechanism
        for unpacking downloaded files, rather than the old tar.h 
        stuff.

If you guys decide to accept this, let me know and I'll talk to my boss
about getting a release form signed.  It won't be a problem, I'm sure. 
I could have done it earlier, but with my boss, it will be better to say
"Project X has accepted some code I wrote on company time and they need
this release signed before they can include it in the release" than "I
might be writing some code for Project X so will you sign this in case I
decide to?"
-- 
= ICBM Address: 36.8274040 N, 108.0204086 W, alt. 1714m
/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

#if !defined(__ARCHIVE_H_)
#define __ARCHIVE_H_

class Decomp;

#include <sys/types.h>

class Archive 
{
  public:
    Archive () : decomp_(0) { }
    ~Archive ();

	// Opens the archive.  Returns nonzero if successful.
    virtual int open (const char *filename);

	// Opens and unpacks the archive using the given map to map
	// pathnames in the archive to output paths.  Returns 0 on success,
	// or a count of errors on failure.  The map is an array of
	// in/out pathnames, with 0s to mark the end of the map.
	//virtual int auto_unpack (const char* filename, const char** map) = 0;

	// Returns true if the archive is open.
	virtual bool is_open () { return (decomp_ != 0); }

	// returns pointer to buffer containing name of next file
    virtual const char *next_file_name () = 0;

	// Begins reading the given file.  Returns zero on success,
	// nonzero on failure.
	virtual int	read_file (const char *path) = 0;

	// Return the byte position in [compressed] file.
    virtual off_t tell () = 0;

	// Close the archive.  Returns 0 on success, nonzero on failure.
	virtual int close ();

  protected:
	Decomp* decomp_;
};

#endif // !defined(__ARCHIVE_H_)

/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

/* Implements the bzip-format decompression class. */

#include "bzdecomp.h"

#include <fcntl.h>


//// ctor //////////////////////////////////////////////////////////////

BZDecomp::BZDecomp (const char *filename)
{
  fd_ = open (filename, O_RDONLY | O_BINARY);
  if (fd_)
    b_ = BZ2_bzdopen (fd_, "rb");
  else
    b_ = 0;
}


//// read //////////////////////////////////////////////////////////////

int BZDecomp::read (void *buf, int len)
{
  return BZ2_bzread (b_, buf, len);
}


//// close /////////////////////////////////////////////////////////////

int BZDecomp::close ()
{
  if (b_)
    {
      BZ2_bzclose (b_);
      b_ = 0;
      fd_ = 0;
    }
  return 0;
}


//// tell //////////////////////////////////////////////////////////////

off_t BZDecomp::tell ()
{
  return ::tell (fd_);
}

/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

#if !defined(__BZDECOMP_H_)
#define __BZDECOMP_H_

#include "decomp.h"

#undef _WIN32
#include "bzlib.h"

class BZDecomp :
public Decomp
{
  public:
    // Ctor and dtor
    BZDecomp (const char *filename);
    ~BZDecomp ();

    virtual int read (void *buf, int len);
    virtual off_t tell ();
    virtual int close ();

  private:
    BZFILE* b_;
    int fd_;
};

#endif // !defined(__BZDECOMP_H_)

/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

/* Implements the file type recognition logic.  We create subclasses of
   Decomp depending on what type of file we think we're dealing with. */

#include "decomp.h"
#include "gzdecomp.h"
#include "bzdecomp.h"

#include <string.h>


//// factory ///////////////////////////////////////////////////////////
// Virtual ctor: we examine the file for magic bytes and return an
// instance of Decomp if we can figure out what kind of file it is.  If
// we can't figure it out or there is another error (e.g. the file isn't
// there) we return 0.

Decomp *Decomp::factory (const char *filename)
{
  // Open the file
  FILE *fp = fopen (filename, "r");
  if (!fp)
    {
      return 0;
    }

  // In all file types we know about, the magic bytes are located
  // among the first few bytes, so read them in.
  char ac[3];
  if (fread (ac, 1, sizeof (ac), fp) < sizeof (ac))
    {
      fclose (fp);
      return 0;
    }
  fclose (fp);

  // Check for magic bytes we understand.
  if (memcmp (ac, "\037\213", 2) == 0)
    {
      return new GZDecomp (filename);
    }
  else if (memcmp (ac, "BZh", 3) == 0)
    {
      return new BZDecomp (filename);
    }
  else
    {
      return 0;
    }
}


//// dtor //////////////////////////////////////////////////////////////

Decomp::~Decomp ()
{
  close ();
}


//// close /////////////////////////////////////////////////////////////
// Dummy implementation to make the linker happy, because we call
// close() from the dtor.

int Decomp::close ()
{
  return 0;
}

/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

#if !defined(__DECOMP_H_)
#define __DECOMP_H_

#include <sys/types.h>

#include <stdio.h>

class Decomp
{
  public:
    // Factory to create one of our subclasses by examining the file's
    // structure.
    static Decomp *factory (const char *filename);

   ~Decomp ();

    virtual int read (void *buf, int len) = 0;
    virtual off_t tell () = 0;
    virtual int close () = 0;

  protected:
    Decomp () { }
};

#endif // !defined(__DECOMP_H_)
/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

/* Implements the gzip-format decompression class. */

#include "gzdecomp.h"


//// ctor //////////////////////////////////////////////////////////////

GZDecomp::GZDecomp (const char *filename)
{
  g_ = gzopen (filename, "rb");
}


//// read //////////////////////////////////////////////////////////////

int GZDecomp::read (void *buf, int len)
{
  return gzread (g_, buf, len);
}


//// close /////////////////////////////////////////////////////////////

int GZDecomp::close ()
{
  gzFile g = g_;
  g_ = 0;

  if (g)
    {
      return gzclose (g);
    }
  else
    {
      return 0;
    }
}


//// tell //////////////////////////////////////////////////////////////

off_t GZDecomp::tell ()
{
  return gzctell (g_);
}

/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

#if !defined(__GZDECOMP_H_)
#define __GZDECOMP_H_

#include "decomp.h"

#include "zlib/zlib.h"

class GZDecomp :
public Decomp
{
  public:
    // Ctor and dtor
    GZDecomp (const char *filename);
    ~GZDecomp ();

    virtual int read (void *buf, int len);
    virtual off_t tell ();
    virtual int close ();

  private:
    gzFile g_;
};

#endif // !defined(__GZDECOMP_H_)

--- install.cc.orig	Tue Nov  6 05:41:50 2001
+++ install.cc	Tue Nov  6 05:50:07 2001
@@ -346,10 +346,11 @@
 
   SetWindowText (ins_action, msg);
   log (0, "%s%s", msg, file);
-  tar_open (file);
+  Archive* arch = new TarArchive;
+  arch->open(file);
 
-  char *fn;
-  while (fn = tar_next_file ())
+  const char *fn;
+  while (fn = arch->next_file_name ())
     {
       char *dest_file;
 
@@ -360,17 +361,17 @@
 
       SetWindowText (ins_filename, dest_file);
       log (LOG_BABBLE, "Installing file %s", dest_file);
-      if (tar_read_file (dest_file) != 0)
+      if (arch->read_file (dest_file) != 0)
 	{
 	  log (0, "Unable to install file %s", dest_file);
 	  errors++;
 	}
 
-      progress (tar_ftell ());
+      progress (arch->tell ());
       free (dest_file); 
       num_installs++;
     }
-  tar_close ();
+  delete arch;
 
   total_bytes_sofar += file_size;
   progress (0);
--- Makefile.in.orig	Tue Nov  6 02:43:51 2001
+++ Makefile.in	Tue Nov  6 03:54:08 2001
@@ -73,9 +73,12 @@
 PROGS	:= setup$(EXEEXT)
 
 OBJS = \
+    archive.o \
 	autoload.o \
+	bzdecomp.o \
 	choose.o \
 	concat.o \
+	decomp.o \
 	desktop.o \
 	dialog.o \
 	diskfull.o \
@@ -83,6 +86,7 @@
 	find.o \
 	fromcwd.o \
 	geturl.o \
+	gzdecomp.o \
 	hash.o \
 	ini.o \
 	inilex.o \
/*
 * Copyright (c) 2000, 2001, Red Hat, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by DJ Delorie <dj@cygnus.com>
 *
 */

/* Built-in tar functionality.  See archive.h for usage. */

static char *cvsid = "\n%%% $Id: tar.cc,v 2.5 2001/06/13 16:11:01 cgf Exp $\n";

#include "tar.h"
#include "decomp.h"

#include "win32.h"
#include "mkdir.h"
#include "log.h"
#include "filemanip.h"
#include "port.h"

#include <sys/types.h>
#include <sys/fcntl.h>

#include <stdio.h>


#define FACTOR (0x19db1ded53ea710LL)
#define NSPERSEC 10000000LL
#define SYMLINK_COOKIE "!<symlink>"


// Debugging mechanism.
static int _tar_verbose = 0;
static FILE * _tar_vfile = 0;
#define vp if (_tar_verbose) fprintf
#define vp2 if (_tar_verbose>1) fprintf


//// ::xstrdup /////////////////////////////////////////////////////////

static char *
xstrdup (const char *c)
{
  char *r = (char *) malloc (strlen (c) + 1);
  if (!r)
    exit_setup (1);
  strcpy (r, c);
  return r;
}


//// ::prepare_for_file ////////////////////////////////////////////////

static void
prepare_for_file (const char *path)
{
  DWORD w;
  mkdir_p (0, path);

  w = GetFileAttributes (path);
  if (w != 0xffffffff && w & FILE_ATTRIBUTE_DIRECTORY)
    {
      char *tmp = (char *) malloc (strlen (path) + 10);
      int i = 0;
      do {
	i++;
	sprintf (tmp, "%s.old-%d", path, i);
      } while (GetFileAttributes (tmp) != 0xffffffff);
      fprintf (stderr, "warning: moving directory \"%s\" out of the way.\n", path);
      MoveFile (path, tmp);
      free (tmp);
    }

  DeleteFileA (path);
}


//// ctor //////////////////////////////////////////////////////////////

TarArchive::TarArchive () :
have_longname_(false),
file_length_(0),
map_result_(0),
err_(0)
//map_(0),
//nmaps_(0)
{
  file_name_[0] = '\0';

  if (sizeof (header_) != 512)
    {
      /* drastic, but important */
      fprintf (stderr, "compilation error: tar header struct not 512"
	       " bytes (it's %d)\n", sizeof (header_));
      exit_setup (1);
    }

  if (_tar_vfile == 0)
    {
      _tar_vfile = stderr;
	}
}



//// open //////////////////////////////////////////////////////////////

int
TarArchive::open (const char *pathname)
{
  vp2 (_tar_vfile, "tar: open `%s'\n", pathname);

  DWORD size = get_file_size (pathname);
  if (size == 0)
    return 1;

  err_ = 0;
  return Archive::open(pathname);
}


//// tell //////////////////////////////////////////////////////////////

off_t
TarArchive::tell ()
{
  return decomp_->tell ();
}



//// skip_file /////////////////////////////////////////////////////////

void
TarArchive::skip_file ()
{
  while (file_length_ > 0)
    {
      decomp_->read (buf_, sizeof (buf_));
      file_length_ -= sizeof (buf_);
    }
}


//// next_file_name ////////////////////////////////////////////////////

const char *
TarArchive::next_file_name ()
{
  int r, n;
  char *c;
  r = decomp_->read (&header_, sizeof (header_));

  /* See if we're at end of file */
  if (r != sizeof(header_))
    return 0;

  /* See if the header is all zeros (i.e. last block) */
  n = 0;
  for (r = sizeof(header_) / sizeof (int); r; r--)
    n |= ((int *)&header_)[r-1];
  if (n == 0)
    return 0;

  if (!have_longname_ && header_.typeflag != 'L')
    {
      memcpy (file_name_, header_.name, 100);
      file_name_[100] = 0;
    }

  sscanf (header_.size, "%o", &file_length_);

  vp2 (_tar_vfile, "%c %9d %s\n", header_.typeflag, file_length_,
	  file_name_);

  switch (header_.typeflag)
    {
    case 'L': /* GNU tar long name extension */
      if (file_length_ > _MAX_PATH)
	{
	  skip_file ();
	  fprintf (stderr, "error: long file name exceeds %d characters\n",
		   _MAX_PATH);
	  ++err_;
	  decomp_->read (&header_, sizeof (header_));
	  sscanf (header_.size, "%o", &file_length_);
	  skip_file ();
	  return next_file_name ();
	}
      c = file_name_;
      while (file_length_ > 0)
	{
	  int need = file_length_ > sizeof (buf_) ? sizeof (buf_) :
	  		file_length_;
	  if (decomp_->read (buf_, sizeof(buf_)) < sizeof(buf_))
	    return 0;
	  memcpy (c, buf_, need);
	  c += need;
	  file_length_ -= need;
	}
      *c = 0;
      have_longname_ = true;
      return next_file_name ();

    case '3': /* char */
    case '4': /* block */
    case '6': /* fifo */
      fprintf (stderr, "warning: not extracting special file %s\n",
	       file_name_);
      ++err_;
      return next_file_name ();

    case '0': /* regular file */
    case 0: /* regular file also */
    case '2': /* symbolic link */
    case '5': /* directory */
    case '7': /* contiguous file */
      return file_name_;

    case '1': /* hard link, we just copy */
      return file_name_;

    default:
      fprintf (stderr, "error: unknown (or unsupported) file type `%c'\n",
	       header_.typeflag);
      ++err_;
      skip_file ();
      return next_file_name ();
    }
}


//// fix_time_stamp ////////////////////////////////////////////////////

void
TarArchive::fix_time_stamp (const char *path)
{
  int mtime;
  long long ftimev;
  FILETIME ftime;
  HANDLE h;

  sscanf (header_.mtime, "%o", &mtime);
  ftimev = mtime * NSPERSEC + FACTOR;
  ftime.dwHighDateTime = ftimev >> 32;
  ftime.dwLowDateTime = ftimev;
  h = CreateFileA (path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
		   0, OPEN_EXISTING,
		   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
  if (h)
    {
      SetFileTime (h, 0, 0, &ftime);
      CloseHandle (h);
    }
}


//// common_fopen //////////////////////////////////////////////////////

FILE *
TarArchive::common_fopen (const char *path)
{
  FILE *out;
  out = fopen (path, "wb");
  if (!out)
    {
      /* maybe we need to create a directory */
      if (mkdir_p (0, path))
	{
	  skip_file ();
	  return 0;
	}
      out = fopen (path, "wb");
    }
  if (!out)
    {
      fprintf (stderr, "unable to write to file %s\n", path);
      perror ("The error was");
      skip_file ();
      return 0;
    }
  return out;
}


//// read_file /////////////////////////////////////////////////////////

int
TarArchive::read_file (const char *path)
{
  FILE *out, *copy;
  HANDLE h;
  DWORD w, startticks;
  int got;
  map_result_type *tmr;

  switch (header_.typeflag)
    {
    case '0':	/* regular files */
    case 0:
    case '7':
      vp (_tar_vfile, "F %s\n", path);
      prepare_for_file (path);
      out = common_fopen (path);
      if (!out)
	return 1;

      while (file_length_ > 0)
	{
	  int put;
	  int want = file_length_ > sizeof (buf_) ? sizeof (buf_) :
	  	  file_length_;
	  got = decomp_->read (buf_, sizeof(buf_));
	  if (got < sizeof(buf_))
	    {
	      fprintf (stderr, "tar: unexpected end of file reading %s\n", path);
	      fclose (out);
	      remove (path);
	      return 1;
	    }
	  put = fwrite (buf_, 1, want, out);
	  if (put < want)
	    {
	      fprintf (stderr, "tar: out of disk space writing %s\n", path);
	      fclose (out);
	      remove (path);
	      skip_file ();
	      return 1;
	    }
	  file_length_ -= want;
	}
      fclose (out);

      fix_time_stamp (path);

      /* we need this to do hard links below */
      tmr = (map_result_type *) malloc (sizeof (map_result_type));
      tmr->next = map_result_;
      tmr->stored_name = xstrdup (file_name_);
      tmr->mapped_name = xstrdup (path);
      map_result_ = tmr;

      return 0;

    case '1':	/* hard links; we just copy */
      for (tmr = map_result_; tmr; tmr=tmr->next)
	if (strcmp (tmr->stored_name, header_.linkname) == 0)
	  break;
      if (!tmr)
	{
	  fprintf (stderr, "tar: can't find %s to link %s to\n",
		   header_.linkname, path);
	  return 1;
	}
      vp (_tar_vfile, "H %s <- %s\n", path, tmr->mapped_name);
      prepare_for_file (path);
      copy = fopen (tmr->mapped_name, "rb");
      if (!copy)
	{
	  fprintf (stderr, "tar: unable to read %s\n", tmr->mapped_name);
	  return 1;
	}
      out = common_fopen (path);
      if (!out)
	return 1;

      while ((got = fread (buf_, 1, sizeof(buf_), copy)) > 0)
	{
	  int put = fwrite (buf_, 1, got, out);
	  if (put < got)
	    {
	      fprintf (stderr, "tar: out of disk space writing %s\n", path);
	      fclose (out);
	      fclose (copy);
	      remove (path);
	      return 1;
	    }
	}
      fclose (out);
      fclose (copy);

      fix_time_stamp (path);
      return 0;

    case '5':	/* directories */
      vp (_tar_vfile, "D %s\n", path); 
	  {
	    char* new_path = xstrdup(path);

		while (new_path[0] && new_path[strlen (new_path)-1] == '/')
		  {
		    new_path[strlen (new_path) - 1] = 0;
		  }
		int retval = mkdir_p (1, new_path);
		free(new_path);
		return retval;
	  }


    case '2':	/* symbolic links */
      vp (_tar_vfile, "L %s -> %s\n", path, header_.linkname);
      prepare_for_file (path);
      h = CreateFileA (path, GENERIC_WRITE, 0, 0, CREATE_NEW,
		      FILE_ATTRIBUTE_NORMAL, 0);
      if (h == INVALID_HANDLE_VALUE)
	{
	  fprintf (stderr, "error: unable to create symlink \"%s\" -> \"%s\"\n",
		   path, header_.linkname);
	  return 1;
	}
      strcpy (buf_, SYMLINK_COOKIE);
      strcat (buf_, header_.linkname);
      if (WriteFile (h, buf_, strlen (buf_) + 1, &w, NULL))
	{
	  CloseHandle (h);
	  SetFileAttributesA (path, FILE_ATTRIBUTE_SYSTEM);
	  return 0;
	}
      CloseHandle (h);
      fprintf (stderr, "error: unable to write symlink \"%s\"\n", path);
      DeleteFileA (path);
      return 1;
    }
}


//// close /////////////////////////////////////////////////////////////

int
TarArchive::close ()
{
  map_result_ = 0;

  if (decomp_->close ())
    ++err_;

  return err_; /* includes errors for skipped files, etc */
}


//// auto_unpack ///////////////////////////////////////////////////////

#if 0		//! No one calls this!
int
TarArchive::auto_unpack (const char *pathname, const char **maplist)
{
  const char *c;
  int i, j;
  map_type mtemp;
  char newname[_MAX_PATH+512];
  static char twiddles[] = "|\b/\b-\b\\\b";
  int t = 0;

  err_ = 0;

  for (nmaps_=0; maplist[nmaps_*2]; nmaps_++) ;
  map_ = (map_type *) malloc ((nmaps_+1) * sizeof (map_type));
  for (nmaps_=0; maplist[nmaps_*2]; nmaps_++)
    {
      map_[nmaps_].from = maplist[nmaps_*2];
      map_[nmaps_].from_len = strlen (maplist[nmaps_*2]);
      map_[nmaps_].to = maplist[nmaps_*2+1];
      map_[nmaps_].to_len = strlen (maplist[nmaps_*2+1]);
    }
  /* bubble sort - expect the maps to be short */
  for (i=0; i<nmaps_-1; i++)
    for (j=i+1; j<nmaps_; j++)
      if (map_[i].from_len < map_[j].from_len)
	{
	  mtemp = map_[i];
	  map_[i] = map_[j];
	  map_[j] = mtemp;
	}

  if (open (pathname))
    return 1;
  while (c = next_file_name ())
    {
      int l = strlen (c);
      for (i=0; i<nmaps_; i++)
	if (l >= map_[i].from_len
	    && strncmp (c, map_[i].from, map_[i].from_len) == 0)
	  {
	    strcpy (newname, map_[i].to);
	    strcpy (newname+map_[i].to_len, c + map_[i].from_len);
	    c = newname;
	    break;
	  }

      t = (t+2) % 8;
      fwrite (twiddles+t, 1, 2, stderr);

      if (read_file (c))
	++err_;
    }

  if (close ())
    ++err_;

  fwrite (" \b", 1, 2, stderr);

  vp2 (_tar_vfile, "auto_unpack returns %d\n", err_);
  return err_;
}
#endif


/*
 * Copyright (c) 2000, Red Hat, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by DJ Delorie <dj@cygnus.com>
 *
 */

/* Implements the tar type archive handling.  See archive.h for
 * interface details.
 */

#ifndef __TAR_H_
#define __TAR_H_

#include "archive.h"

#include <stdio.h>
#include <stdlib.h>


class TarArchive :
public Archive
{
  public:
    TarArchive ();
    ~TarArchive ();

    int open (const char *filename);
	//! int auto_unpack (const char* filename, const char** map);
	int close ();

    const char *next_file_name ();
	int	read_file (const char *path);

    off_t tell ();

  protected:
    //// Internal types
	struct header_type {
	  char name[100];       /*   0 */
	  char mode[8];         /* 100 */
	  char uid[8];          /* 108 */
	  char gid[8];          /* 116 */
	  char size[12];        /* 124 */
	  char mtime[12];       /* 136 */
	  char chksum[8];       /* 148 */
	  char typeflag;        /* 156 */
	  char linkname[100];   /* 157 */
	  char magic[6];        /* 257 */
	  char version[2];      /* 263 */
	  char uname[32];       /* 265 */
	  char gname[32];       /* 297 */
	  char devmajor[8];     /* 329 */
	  char devminor[8];     /* 337 */
	  char prefix[155];     /* 345 */
	  char junk[12];		/* 500 */
	};

	struct map_result_type {
	  map_result_type *next;
	  char *stored_name;
	  char *mapped_name;
	};

#if 0		//! No one uses these!
	struct map_type {
	  const char *from;
	  int from_len;
	  const char *to;
	  int to_len;
	};
#endif

	//// Internal support functions
	void skip_file ();
	void fix_time_stamp (const char *path);
	FILE* common_fopen (const char *path);

  private:
  	//// Internal data
    char file_name_[_MAX_PATH + 512];
	bool have_longname_;
	int file_length_;

	map_result_type *map_result_;
	int err_;

	header_type header_;
	char buf_[512];

#if 0		//! No one uses these!
	map_type *map_;		//! Can't these be local to auto_unpack()?
	int nmaps_;
#endif
};

#endif // !defined(__TAR_H)

/*
 * Copyright (c) 2001, Educational Technology Resources, Inc.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 */

/* Implements the generic archive file handling logic. */

#include "archive.h"
#include "decomp.h"



//// dtor //////////////////////////////////////////////////////////////

Archive::~Archive ()
{
  if (is_open()) 
    {
	  close();
  	}
}


//// open //////////////////////////////////////////////////////////////

int
Archive::open (const char* filename)
{
  decomp_ = Decomp::factory(filename);
  return is_open() ? 0 : 1;
}


//// close /////////////////////////////////////////////////////////////

int
Archive::close ()
{
  delete decomp_;
  decomp_ = 0;

  return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]