view nt/minitar.c @ 5607:1a507c4c6c42

Refactor out sequence-oriented builtins from fns.c to the new sequence.c. src/ChangeLog addition: 2011-12-04 Aidan Kehoe <kehoea@parhasard.net> * Makefile.in.in (objs): * depend: Add sequence.o to the list of objects and dependencies. * alloc.c: * alloc.c (mark_bit_vector): * alloc.c (print_bit_vector): * alloc.c (bit_vector_equal): * alloc.c (internal_bit_vector_equalp_hash): * alloc.c (bit_vector_hash): * alloc.c (init_alloc_once_early): Move the implementation of the bit vector type here from fns.c. * emacs.c (main_1): Call syms_of_sequence() here, now sequence.c is included. * fns.c (Fold_rassq): Move this together with the rest of the Fold_* functions. * fns.c: * fns.c (syms_of_fns): Move most functions dealing with sequences generally, and especially those taking key arguments, to a separate file, sequence.c. * general-slots.h: Qyes_or_no_p belong here, not fns.c. * lisp.h: Make Flist_length available here, it's used by sequence.c * sequence.c: * sequence.c (check_sequence_range): * sequence.c (Flength): * sequence.c (check_other_nokey): * sequence.c (check_other_key): * sequence.c (check_if_key): * sequence.c (check_match_eq_key): * sequence.c (check_match_eql_key): * sequence.c (check_match_equal_key): * sequence.c (check_match_equalp_key): * sequence.c (check_match_other_key): * sequence.c (check_lss_key): * sequence.c (check_lss_key_car): * sequence.c (check_string_lessp_key): * sequence.c (check_string_lessp_key_car): * sequence.c (get_check_match_function_1): * sequence.c (get_merge_predicate): * sequence.c (count_with_tail): * sequence.c (list_count_from_end): * sequence.c (string_count_from_end): * sequence.c (Fcount): * sequence.c (Fsubseq): * sequence.c (list_position_cons_before): * sequence.c (FmemberX): * sequence.c (Fadjoin): * sequence.c (FassocX): * sequence.c (FrassocX): * sequence.c (position): * sequence.c (Fposition): * sequence.c (Ffind): * sequence.c (delq_no_quit_and_free_cons): * sequence.c (FdeleteX): * sequence.c (FremoveX): * sequence.c (list_delete_duplicates_from_end): * sequence.c (Fdelete_duplicates): * sequence.c (Fremove_duplicates): * sequence.c (Fnreverse): * sequence.c (Freverse): * sequence.c (list_merge): * sequence.c (array_merge): * sequence.c (list_array_merge_into_list): * sequence.c (list_list_merge_into_array): * sequence.c (list_array_merge_into_array): * sequence.c (Fmerge): * sequence.c (list_sort): * sequence.c (array_sort): * sequence.c (FsortX): * sequence.c (Ffill): * sequence.c (mapcarX): * sequence.c (shortest_length_among_sequences): * sequence.c (Fmapconcat): * sequence.c (FmapcarX): * sequence.c (Fmapvector): * sequence.c (Fmapcan): * sequence.c (Fmap): * sequence.c (Fmap_into): * sequence.c (Fsome): * sequence.c (Fevery): * sequence.c (Freduce): * sequence.c (replace_string_range_1): * sequence.c (Freplace): * sequence.c (Fnsubstitute): * sequence.c (Fsubstitute): * sequence.c (subst): * sequence.c (sublis): * sequence.c (Fsublis): * sequence.c (nsublis): * sequence.c (Fnsublis): * sequence.c (Fsubst): * sequence.c (Fnsubst): * sequence.c (tree_equal): * sequence.c (Ftree_equal): * sequence.c (mismatch_from_end): * sequence.c (mismatch_list_list): * sequence.c (mismatch_list_string): * sequence.c (mismatch_list_array): * sequence.c (mismatch_string_array): * sequence.c (mismatch_string_string): * sequence.c (mismatch_array_array): * sequence.c (get_mismatch_func): * sequence.c (Fmismatch): * sequence.c (Fsearch): * sequence.c (venn): * sequence.c (nvenn): * sequence.c (Funion): * sequence.c (Fset_exclusive_or): * sequence.c (Fnset_exclusive_or): * sequence.c (syms_of_sequence): Add this file, containing those general functions that dealt with sequences that were in fns.c. * symsinit.h: Make syms_of_sequence() available here. man/ChangeLog addition: 2011-12-04 Aidan Kehoe <kehoea@parhasard.net> * internals/internals.texi (Basic Lisp Modules): Document sequence.c here too.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 04 Dec 2011 18:42:50 +0000
parents b694dfd2f40e
children
line wrap: on
line source


/* Minitar:  extract .tar.gz files on Win32 platforms. 
   Uses zlib for decompression.
   
   This is very simple-minded, it ignores checksums, and any type of file 
   that is not a plain file or a directory.  Nonetheless it is useful.

   Author: Charles G. Waldman (cgw@pgt.com),  Aug 4 1998

   This file is placed in the public domain; you can
   do whatever you like with it.  There is NO WARRANTY. 
   If it breaks, you get to keep both pieces */


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <io.h>
#ifdef WIN32_NATIVE
# include <direct.h>	/* For mkdir */
#endif

#include <zlib.h>

static void
Usage (char *name)
{
  fprintf (stderr, "Usage: %s file.tar.gz [base-dir]\n", name);
  fprintf (stderr, "\tExtracts the contents compressed tar file to base-dir\n");
  exit (-1);
}


#define BLOCKSIZE 512
#define MAXNAMELEN 1024

static int
octal (char *str)
{
  int ret = -1;
  sscanf (str, "%o", &ret);
  return ret;
}

/* this is like mkdir -p, except if there is no trailing slash,
   the final component is assumed to be a file, rather than a
   path component, so it is not created as a directory */

static int
makepath (char *path)
{
  char tmp[MAXNAMELEN];
  char *cp;

  for (cp=path; cp; cp = (char*)strchr (cp+1, '/'))
    {
      if (!*cp)
	break;
      if (*cp != '/')
	continue;
      strncpy (tmp, path, cp-path);
      tmp[cp-path] = '\0';
      if (strlen (tmp) == 0)
	continue;
#ifdef WIN32_NATIVE
      if (mkdir (tmp))
#else
	if (mkdir (tmp, 0777))
#endif
	  {
	    if (errno == EEXIST)
	      continue;
	    else
	      return -1;
	  }
    }
  return 0;
}



int
main (int argc, char **argv)
{
  char fullname[MAXNAMELEN];
  char *basedir = ".";
  char *tarfile;
  int size;
  char osize[13];
  char name[101];
  char magic[7];
  char type;
  
  gzFile *infile = (gzFile*)0;
  FILE *outfile = (FILE*)0;

  char block[BLOCKSIZE];
  int nbytes, nread, nwritten;

  int in_block = 0;
  int directory = 0;

  if (argc < 2 || argc > 3)
    Usage (argv[0]);

  tarfile = argv[1];
  if (argc==3)
    basedir = argv[2];

  if (! (infile = gzopen (tarfile, "rb")))
    {
      fprintf (stderr, "Cannot open %s\n", tarfile);
      exit (-2);
    }
  
  while (1)
    {
      nread = gzread (infile, block, 512);

      if (!in_block && nread == 0)
	break;

      if (nread != BLOCKSIZE)
	{
	  fprintf (stderr, "Error: incomplete block read. Exiting.\n");
	  exit (-2);
	}

      if (!in_block)
	{
	  if (block[0]=='\0')  /* We're done */
	    break;

	  strncpy (magic, block+257, 6);
	  magic[6] = '\0';
	  if (strcmp (magic, "ustar "))
	    {
	      fprintf (stderr,
		       "Error: incorrect magic number in tar header. Exiting\n");
	      exit (-2);
	    }

	  strncpy (name, block, 100);
	  name[100] = '\0';
	  sprintf (fullname, "%s/%s", basedir, name);
	  printf ("%s\n", fullname);
	  type = block[156];
      
	  switch (type)
	    {
	    case '0':
	    case '\0':
	      directory = 0;
	      break;
	    case '5':
	      directory = 1;
	      break;
	    default:
	      fprintf (stderr, "Error: unknown type flag %c. Exiting.\n", type);
	      exit (-2);
	      break;
	    }
      
	  if (directory)
	    {
	      in_block = 0;
	
	      /* makepath will ignore the final path component, so make sure 
		 dirnames have a trailing slash */

	      if (fullname[strlen (fullname)-1] != '/')
		strcat (fullname, "/");
	      if (makepath (fullname))
		{
		  fprintf (stderr, "Error: cannot create directory %s. Exiting.\n",
			   fullname);
		  exit (-2);
		}
	      continue;
	    }
	  else
	    { /*file */
	      in_block = 1;
	      if (outfile)
		{
		  if (fclose (outfile))
		    {
		      fprintf (stderr, "Error: cannot close file %s. Exiting.\n",
			       fullname);
		      exit (-2);
		    }
		  outfile = (FILE*)0;
		}

	      if (!(outfile = fopen (fullname, "wb")))
		{
		  /*try creating the directory, maybe it's not there */
		  if (makepath (fullname))
		    {
		      fprintf (stderr, "Error: cannot create file %s. Exiting.\n",
			       fullname);
		      exit (-2);
		    }
		  /* now try again to open the file */
		  if (!(outfile = fopen (fullname, "wb")))
		    {
		      fprintf (stderr, "Error: cannot create file %s. Exiting.\n",
			       fullname);
		      exit (-2);
		    }
		}

	      strncpy (osize, block+124, 12);
	      osize[12] = '\0';
	      size = octal (osize);
	      if (size<0)
		{
		  fprintf (stderr, "Error: invalid size in tar header. Exiting.\n");
		  exit (-2);
		}
	      if (size==0)	/* file of size 0 is done */
		in_block = 0;
	    }
	}
      else
	{ /* write or continue writing file contents */
	  nbytes = size>512? 512:size;
      
	  nwritten = fwrite (block, 1, nbytes, outfile);
	  if (nwritten != nbytes)
	    {
	      fprintf (stderr, "Error: only wrote %d bytes to file %s. Exiting.\n",
		       nwritten, fullname);
	      exit (-2);
	    }
	  size -= nbytes;
	  if (size==0)
	    in_block = 0;
	}
    }
  return 0;
}