Logo Search packages:      
Sourcecode: ksh version File versions  Download package

tp.c

#pragma prototyped

/*
 * pax tp format
 */

#include <paxlib.h>
#include <ccode.h>
#include <tm.h>

#define TP_BLOCK  512

#define DIRDEC          192
#define DIRMAG          496

typedef  uint8_t ui1;
typedef uint16_t ui2;
typedef uint32_t ui4;

typedef struct Dir_s
{
      char  pathname[32];
      ui1   mode[2];
      ui1   uid;
      ui1   gid;
      ui1   unused1;
      ui1   size[3];
      ui1   modtime[4];
      ui1   tapeaddr[2];
      ui1   unused2[16];
      ui1   checksum[2];
} Dir_t;

typedef struct Ar_s
{
      Pax_t*                  pax;
      Paxarchive_t*           ap;
      off_t             offset;
      Dir_t*                  dp;
      Dir_t*                  ep;
      Dir_t             dir[1];
} Ar_t;

static int
tp_done(Pax_t* pax, register Paxarchive_t* ap)
{
      register Ar_t*    ar = (Ar_t*)ap->data;

      if (!ar)
            return -1;
      ap->io->eof = 1;
      free(ar);
      ap->data = 0;
      return 0;
}

static int
tp_getprologue(Pax_t* pax, Paxformat_t* fp, register Paxarchive_t* ap, Paxfile_t* f, unsigned char* buf, size_t size)
{
      register Ar_t*          ar;
      register ui1*           s;
      register ui1*           e;
      int16_t                 w;
      size_t                  n;

      if (size < 2 * TP_BLOCK)
            return 0;
      w = 0;
      for (e = (s = (ui1*)buf + TP_BLOCK) + TP_BLOCK; s < e; s += 2)
            w += s[0] + (s[1]<<8);
      if (w)
            return 0;
      w = ((Dir_t*)buf)->checksum[0] + (((Dir_t*)buf)->checksum[1]<<8);
      if (w < 0 || w > DIRMAG)
            w = DIRMAG;
      n = (size_t)w * sizeof(Dir_t);
      if (!(ar = newof(0, Ar_t, 1, n - sizeof(Dir_t))))
            return paxnospace(pax);
      if (paxread(pax, ap, NiL, PAX_BLOCK, 0, 0) != PAX_BLOCK || paxread(pax, ap, ar->dir, n, 0, 0) != n)
      {
            error(2, "%s: %s format directory read error", ap->name, fp->name);
            free(ar);
            return -1;
      }
      ar->dp = ar->dir;
      ar->ep = ar->dir + w;
      ar->pax = pax;
      ar->ap = ap;
      ap->data = ar;
      return 1;
}

static int
tp_getheader(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f)
{
      register Ar_t*          ar = (Ar_t*)ap->data;
      register Dir_t*         dp;
      register ui1*           s;
      register ui1*           e;
      int16_t                 w;

      do
      {
            if (ar->dp >= ar->ep)
                  return 0;
            dp = ar->dp++;
      } while (!*dp->pathname);
      w = 0;
      for (e = (s = (ui1*)ar->dir) + sizeof(Dir_t); s < e; s += 2)
            w += s[0] + (s[1]<<8);
      if (w)
      {
            error(2, "%s: %s format directory entry %d checksum error", ap->name, ap->format->name, ar->dp - ar->dir);
            return -1;
      }
      if (CC_NATIVE != CC_ASCII)
            ccmaps(dp->pathname,  sizeof(dp->pathname), CC_ASCII, CC_NATIVE);
      f->name = dp->pathname;
      f->linktype = PAX_NOLINK;
      f->linkpath = 0;
      f->st->st_mode = X_IFREG | ((dp->mode[0] + (dp->mode[1]<<8)) & 07777);
      f->st->st_uid = dp->uid;
      f->st->st_gid = dp->gid;
      f->st->st_size = (dp->size[0]<<16) + dp->size[1] + (dp->size[2]<<8);
      f->st->st_mtime = dp->modtime[2] + (dp->modtime[3]<<8) + (dp->modtime[0]<<16) + (dp->modtime[1]<<24);
      f->st->st_nlink = 1;
      ar->offset = (off_t)(dp->tapeaddr[0] + (dp->tapeaddr[1]<<8)) * TP_BLOCK;
      return 1;
}

static int
tp_getdata(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f, int fd)
{
      Sfio_t*           sp;
      off_t       skip;
      ssize_t           n;
      int         r;

      if (!(n = f->st->st_size))
            return 1;
      skip = roundof(f->st->st_size, TP_BLOCK);
      r = -1;
      if (fd < 0)
            r = 1;
      else if (sp = paxpart(pax, ap, f->st->st_size))
            for (;;)
            {
                  if ((n = sfread(sp, pax->buf, sizeof(pax->buf))) < 0)
                  {
                        (*pax->errorf)(NiL, pax, 2, "%s: %s: unexpected EOF", ap->name, f->name);
                        break;
                  }
                  else if (n == 0)
                        break;
                  skip -= n;
                  if (paxdata(pax, ap, f, fd, pax->buf, n))
                        break;
            }
      if (skip && paxread(pax, ap, NiL, skip, 0, 0) != skip)
      {
            (*pax->errorf)(NiL, pax, 2, "%s: %s: cannot skip past %s format data", ap->name, f->name, ap->format->name);
            r = -1;
      }
      return r;
}

Paxformat_t pax_tp_format =
{
      "tp",
      0,
      "unix 4th-7th edition PDP-11 tp archive",
      0,
      PAX_ARCHIVE|PAX_NOHARDLINKS|PAX_IN,
      PAX_DEFBUFFER,
      PAX_DEFBLOCKS,
      PAX_BLOCK,
      PAXNEXT(pax_tp_next),
      0,
      tp_done,
      tp_getprologue,
      tp_getheader,
      tp_getdata,
};

PAXLIB(&pax_tp_format)

Generated by  Doxygen 1.6.0   Back to index