/*
 * This file is part of uudeview, the simple and friendly multi-part multi-
 * file uudecoder  program  (c)  1994 by Frank Pilhofer. The author may be
 * contacted by his email address,          fp@informatik.uni-frankfurt.de
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */


#include <stdio.h>

#ifndef NO_POSIX
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#endif

#ifndef _DOS
#include <unistd.h>
#endif

#include "uudeview.h"
#include "uuerror.h"
#include "uutar.h"
#include "uuutil.h"
#include "uuio.h"
#include "uufree.h"

uulist *tar2bin (uulist *uthis)
{
  FILE *datin, *datout;
  char *tname;

  if (uthis == NULL)
    return NULL;
  if (uthis->tarblock == -1)
    return NULL;

  if ((tname = tempnam (NULL, "uu")) == NULL) {
    uuerror = FILEERR;
    return NULL;
  }

  if ((datin = fopen (uthis->binfile, "rb")) == NULL) {
    uuerror = FILEERR;
    free (tname);
    return NULL;
  }
  if ((datout = fopen (tname, "wb")) == NULL) {
    uuerror = FILEERR;
    fclose (datin);
    free   (tname);
    return NULL;
  }
  if (write_tar (datin, datout, uthis) != 1) {
    uuerror = FILEERR;
    fclose (datout);
    fclose (datin);
    unlink (tname);
    free   (tname);
    return NULL;
  }
  fclose (datout);
  fclose (datin);
  free   (uthis->binfile);

  uthis->tarblock = -1;
  uthis->binfile  = tname;

  return uthis;
}

uulist *tarscan (uulist *uthis)
{
  uulist *unew = NULL, *result = NULL, *iter = NULL;
  long fsize, blockno = 0;
  tarblock uthisblock;
  FILE *tarfile;
  char *ptr;

  if (uthis == NULL)
    return NULL;
 
  if (uthis->branch != NULL)
    return uthis->branch;

  if ((ptr = strrchr (uthis->filename, '.')) == NULL)
    return NULL;

  if (strcmp (ptr, ".tar") != 0)
    return NULL;

  if ((tarfile = fopen (uthis->binfile, "rb")) == NULL) {
    uuerror = FILEERR;
    return NULL;
  }

  while (!feof (tarfile)) {
    if (fread (&uthisblock, 1, TARBLOCK, tarfile) != TARBLOCK) {
      fclose (tarfile);
      return result;
    }
    if (feof (tarfile)) {
      fclose (tarfile);
      return result;
    }
    if (uthisblock.dummy[0] == '\0') {
      fclose (tarfile);
      return result;
    }
    if (uthisblock.header.name[0] == '\0') {
      blockno++;
      continue;
    }
    if (uthisblock.header.linkflag == '\0' ||
	uthisblock.header.linkflag ==  0) {
      blockno++;
      continue;
    }
    if ((unew = (uulist *) malloc (sizeof (uulist))) == NULL) {
      fclose (tarfile);
      killlist (result);
      uthis->branch = NULL;
      uuerror = NOMEM;
      return NULL;
    }
    unew->state     = ST_DECODED;
    unew->mode      = (short) getokt (uthisblock.header.mode);
    unew->filename  = _CopyLine (uthisblock.header.name, -1);
    unew->subfname  = NULL;
    unew->tarblock  = blockno++;
    unew->binfile   = _CopyLine (uthis->binfile, -1);
    unew->thisfile  = NULL;
    unew->misparts  = NULL;
    unew->branch    = NULL;
    unew->NEXT      = NULL;

    if (result == NULL) 
      result = uthis->branch = iter = unew;
    else {
      iter->NEXT = unew;
      iter       = unew;
    }

    fsize = getokt (uthisblock.header.size);

    while (fsize > 0 && !feof (tarfile)) {
      if (fread (&uthisblock, 1, TARBLOCK, tarfile) != TARBLOCK) {
        fclose (tarfile);
        return result;
      }
      fsize -= TARBLOCK;
      blockno++;
    }
  }
  fclose (tarfile);

  return result;
}

