Logo Search packages:      
Sourcecode: ksh version File versions

pax-cpio.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*           Copyright (c) 1987-2007 AT&T Knowledge Ventures            *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                      by AT&T Knowledge Ventures                      *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                                                                      *
***********************************************************************/
#pragma prototyped

/*
 * pax { asc aschk binary cpio } formats
 */

#include "format.h"

#define ASC             1
#define ASCHK                 2
#define BINARY                3
#define CPIO                  4

#define CPIO_MAGIC            070707
#define CPIO_EXTENDED         1
#define CPIO_HEADER           76
#define CPIO_TRAILER          "TRAILER!!!"
#define CPIO_TRUNCATE(x)      ((x)&0177777)
#define CPIO_NAMESIZE         256
#define CPIO_ALIGN            0

#define ASC_HEADER            110
#define ASC_MAGIC       070701
#define ASC_NAMESIZE          1024
#define ASC_ALIGN       4

#define ASCHK_MAGIC           070702

#define BINARY_HEADER         sizeof(Binary_header_t)
#define BINARY_NAMESIZE       256
#define BINARY_ALIGN          2

typedef struct Binary_header_s
{
      short       magic;
      unsigned short    dev;
      unsigned short    ino;
      unsigned short    mode;
      unsigned short    uid;
      unsigned short    gid;
      short       links;
      unsigned short    rdev;
      unsigned short    mtime[2];
      short       namesize;
      unsigned short    size[2];
} Binary_header_t;

typedef struct Localstat_s
{
      long  dev;
      long  ino;
      long  mode;
      long  uid;
      long  gid;
      long  nlink;
      long  rdev;
      long  mtime;
      off_t size;
      long  dev_major;
      long  dev_minor;
      long  rdev_major;
      long  rdev_minor;
      long  checksum;
} Localstat_t;

typedef struct Cpio_s
{
      int   trailer;
#if CPIO_EXTENDED
      char  opsbuf[PATH_MAX]; /* extended ops buffer        */
      char* ops;              /* opsbuf output pointer      */
#endif
} Cpio_t;

#if CPIO_EXTENDED

/*
 * get and execute extended ops from input
 */

static void
getxops(register Archive_t* ap, register File_t* f)
{
      register char*    p;
      register char*    s;
      register int      c;

      if (f->namesize > (c = strlen(f->name) + 1))
            for (p = f->name + c; c = *p++;)
            {
                  for (s = p; *p; p++);
                  p++;
                  message((-2, "%s: %s: entry %d.%d op = %c%s", ap->name, f->name, ap->volume, ap->entry, c, s));
                  switch (c)
                  {
                  case 'd':
                        IDEVICE(f->st, strtol(s, NiL, 16));
                        break;
                  case 'g':
                        f->st->st_gid = strtol(s, NiL, 16);
                        break;
                  case 's':
                        f->st->st_size = strtoll(s, NiL, 16);
                        break;
                  case 'u':
                        f->st->st_uid = strtol(s, NiL, 16);
                        break;
                  case 'G':
                        f->gidname = s;
                        break;
                  case 'U':
                        f->uidname = s;
                        break;

                        /*
                         * NOTE: ignore unknown ops for future extensions
                         */
                  }
            }
}

/*
 * set end of extended ops
 */

static void
setxops(Archive_t* ap, register File_t* f)
{
      register Cpio_t*  cpio = (Cpio_t*)ap->data;
      register int            n;

      if (n = cpio->ops - cpio->opsbuf)
      {
            n++;
            *cpio->ops++ = 0;
            if ((f->namesize += n) > CPIO_NAMESIZE)
                  error(1, "%s: extended ops may crash older cpio programs", f->name);
      }
}

/*
 * output filename and extended ops
 */

static void
putxops(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      register Cpio_t*  cpio = (Cpio_t*)ap->data;
      register int            n;

      n = cpio->ops - cpio->opsbuf;
      paxwrite(pax, ap, f->name, f->namesize -= n);
      if (n)
            paxwrite(pax, ap, cpio->ops = cpio->opsbuf, n);
}


/*
 * add extended op string
 */

static void
addxopstr(Archive_t* ap, int op, register char* s)
{
      register Cpio_t*  cpio = (Cpio_t*)ap->data;
      register char*          p = cpio->ops;
      register char*          e = cpio->opsbuf + sizeof(cpio->opsbuf) - 3;

      if (p < e)
      {
            *p++ = op;
            while (*s && p < e)
                  *p++ = *s++;
            *p++ = 0;
            cpio->ops = p;
      }
#if DEBUG
      if (*s)
            error(PANIC, "addxopstr('%c',\"%s\") overflow", op, s);
#endif
}

/*
 * add extended op number
 */

static void
addxopnum(Archive_t* ap, int op, Sflong_t n)
{
      char  buf[33];

      sfsprintf(buf, sizeof(buf), "%I*x", sizeof(n), n);
      addxopstr(ap, op, buf);
}

#endif

static int
init(Archive_t* ap)
{
      register Cpio_t*  cpio;

      if (ap->data)
      {
            cpio = (Cpio_t*)ap->data;
            memset(cpio, 0, sizeof(*cpio));
      }
      else
      {
            if (!(cpio = newof(0, Cpio_t, 1, 0)))
                  nospace();
            ap->data = cpio;
      }
#if CPIO_EXTENDED
      cpio->ops = cpio->opsbuf;
#endif
      return 1;
}

static int
cpio_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
{
      int         magic;

      if (size >= CPIO_HEADER && buf[0] == '0' && sfsscanf((char*)buf, "%6o", &magic) == 1 && magic == CPIO_MAGIC)
            return init(ap);
      return 0;
}

static int
cpio_common(Pax_t* pax, register Archive_t* ap, register File_t* f, int align, int header)
{
      char*       s;

      f->linktype = NOLINK;
      f->linkpath = 0;
      f->uidname = 0;
      f->gidname = 0;
      switch (ap->format->variant)
      {
      case BINARY:
            align = BINARY_ALIGN;
            header = BINARY_HEADER;
            break;
      case ASC:
      case ASCHK:
            align = ASC_ALIGN;
            header = ASC_HEADER;
            break;
      default:
            align = 0;
            break;
      }
      if (align)
      {
            if (header = (header + f->namesize) % align)
                  align -= header;
            else
                  align = 0;
      }
      f->name = paxstash(pax, &ap->stash.head, NiL, f->namesize + align);
      paxread(pax, ap, f->name, (off_t)0, (off_t)(f->namesize + align), 1);
      if (f->name[f->namesize - 1])
      {
            paxunread(pax, ap, &f->name[f->namesize - 1], 1);
            f->name[f->namesize - 1] = 0;
            error(state.keepgoing ? 1 : 3, "%s: entry %d.%d file name terminating null missing", ap->name, ap->volume, ap->entry);
      }
#if CPIO_EXTENDED
      getxops(ap, f);
#endif
      if (streq(f->name, CPIO_TRAILER))
      {
            ((Cpio_t*)ap->data)->trailer++;
            getdeltaheader(ap, f);
            if (ap->delta)
                  setinfo(ap, f);
            return 0;
      }
      switch (f->type = X_ITYPE(f->st->st_mode))
      {
      case X_IFBLK:
      case X_IFCHR:
      case X_IFDIR:
      case X_IFIFO:
      case X_IFLNK:
      case X_IFREG:
      case X_IFSOCK:
            break;
      default:
            error(1, "%s: %s: unknown file type %07o -- regular file assumed", ap->name, f->name, f->type);
            f->type = X_IFREG;
            break;
      }
      f->st->st_mode &= X_IPERM;
      f->st->st_mode |= f->type;
      switch (f->type)
      {
      case X_IFLNK:
            f->linkpath = paxstash(pax, &ap->stash.link, NiL, f->st->st_size);
            f->linktype = SOFTLINK;
            s = f->linkpath;
            while (paxread(pax, ap, s, (off_t)1, (off_t)1, 1) > 0)
            {
                  f->st->st_size--;
                  if (!*s++)
                        break;
                  if (!f->st->st_size)
                  {
                        *s = 0;
                        break;
                  }
            }
            break;
      default:
            f->linktype = NOLINK;
            break;
      }
      return 1;
}

static int
cpio_done(Pax_t* pax, register Archive_t* ap)
{
      if (ap->data)
      {
            free(ap->data);
            ap->data = 0;
      }
      return 0;
}

static int
cpio_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      Localstat_t lst;

      if (paxread(pax, ap, state.tmp.buffer, (off_t)0, (off_t)CPIO_HEADER, 0) <= 0)
            return 0;
      state.tmp.buffer[CPIO_HEADER] = 0;
      if (state.tmp.buffer[0] == '0' && sfsscanf(state.tmp.buffer, "%6o%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6o%11I*o",
            &f->magic,
            &lst.dev,
            &lst.ino,
            &lst.mode,
            &lst.uid,
            &lst.gid,
            &lst.nlink,
            &lst.rdev,
            &lst.mtime,
            &f->namesize,
            sizeof(lst.size), &lst.size) == 11 && f->magic == CPIO_MAGIC)
      {
            f->st->st_dev = lst.dev;
            f->st->st_ino = lst.ino;
            f->st->st_mode = lst.mode;
            f->st->st_uid = lst.uid;
            f->st->st_gid = lst.gid;
            f->st->st_nlink = lst.nlink;
            IDEVICE(f->st, lst.rdev);
            f->st->st_mtime = lst.mtime;
            f->st->st_size = lst.size;
            return cpio_common(pax, ap, f, CPIO_ALIGN, CPIO_HEADER);
      }
      paxunread(pax, ap, state.tmp.buffer, CPIO_HEADER);
      return 0;
}

static int
cpio_getepilogue(Pax_t* pax, register Archive_t* ap)
{
      register Cpio_t*  cpio = (Cpio_t*)ap->data;

      if (!cpio->trailer)
      {
            error(2, "%s: %s format corrupt -- epilogue (%s) not found", ap->name, ap->format->name, CPIO_TRAILER);
            return -1;
      }
      return 0;
}

static int
cpio_putprologue(Pax_t* pax, Archive_t* ap)
{
      return init(ap);
}

static int
cpio_putheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      if (state.complete)
            complete(ap, f, CPIO_HEADER + f->namesize);
#if CPIO_EXTENDED
      if (!f->skip && !state.strict)
      {
            getidnames(f);
            addxopstr(ap, 'U', f->uidname);
            addxopstr(ap, 'G', f->gidname);
            if (CPIO_TRUNCATE(idevice(f->st)) != idevice(f->st))
                  addxopnum(ap, 'd', (Sflong_t)idevice(f->st));
#if NUMBER_EVEN_THOUGH_NAME
            if (CPIO_TRUNCATE(f->st->st_gid) != f->st->st_gid)
                  addxopnum(ap, 'g', (Sflong_t)f->st->st_gid);
            if (CPIO_TRUNCATE(f->st->st_uid) != f->st->st_uid)
                  addxopnum(ap, 'u', (Sflong_t)f->st->st_uid);
#endif
            if (f->st->st_size > 0x7fffffff)
                  addxopnum(ap, 's', (Sflong_t)f->st->st_size);
            setxops(ap, f);
      }
      else
#endif
      {
            if (CPIO_TRUNCATE(idevice(f->st)) != idevice(f->st))
                  error(1, "%s: special device number truncated", f->name);
            if (CPIO_TRUNCATE(f->st->st_gid) != f->st->st_gid)
                  error(1, "%s: gid number truncated", f->name);
            if (CPIO_TRUNCATE(f->st->st_uid) != f->st->st_uid)
                  error(1, "%s: uid number truncated", f->name);
      }
      sfsprintf(state.tmp.buffer, state.tmp.buffersize, "%0.6lo%0.6lo%0.6lo%0.6lo%0.6lo%0.6lo%0.6lo%0.6lo%0.11lo%0.6o%0.11I*o",
            (long)CPIO_TRUNCATE(CPIO_MAGIC),
            (long)CPIO_TRUNCATE(f->st->st_dev),
            (long)CPIO_TRUNCATE(f->st->st_ino),
            (long)CPIO_TRUNCATE(f->st->st_mode),
            (long)CPIO_TRUNCATE(f->st->st_uid),
            (long)CPIO_TRUNCATE(f->st->st_gid),
            (long)CPIO_TRUNCATE(f->st->st_nlink),
            (long)CPIO_TRUNCATE(idevice(f->st)),
            (long)f->st->st_mtime,
            (long)f->namesize,
            sizeof(intmax_t), (intmax_t)(f->st->st_size + (f->type == X_IFLNK ? f->linkpathsize : 0)));
      paxwrite(pax, ap, state.tmp.buffer, CPIO_HEADER);
#if CPIO_EXTENDED
      putxops(pax, ap, f);
#else
      paxwrite(pax, ap, f->name, f->namesize);
#endif
      if (f->type == X_IFLNK)
      {
            if (streq(f->name, f->linkpath))
                  error(1, "%s: symbolic link loops to self", f->name);
            paxwrite(pax, ap, f->linkpath, f->linkpathsize);
            putdeltaheader(ap, f);
      }
      return 1;
}

static off_t
cpio_putepilogue(Pax_t* pax, Archive_t* ap)
{
      char  buf[sizeof(CPIO_TRAILER)];

      putinfo(ap, strcpy(buf, CPIO_TRAILER), ap->delta && !(ap->delta->format->flags & PSEUDO) ? ap->delta->index + 1 : 0, 0);
      return ap->io->unblocked ? BLOCKSIZE : state.blocksize;
}

static int
cpio_event(Pax_t* pax, Archive_t* ap, File_t* f, void* data, unsigned long event)
{
      off_t       n;

      switch (event)
      {
      case PAX_EVENT_BUG_19951031:
            /*
             * compensate for a pre 19951031 pax bug
             * that added linknamesize to st_size
             */

            if (f->st->st_size == f->linkpathsize && paxread(pax, ap, state.tmp.buffer, (off_t)0, n = f->st->st_size + 6, 0) > 0)
            {
                  paxunread(pax, ap, state.tmp.buffer, n);
                  state.tmp.buffer[6] = 0;
                  state.tmp.buffer[n] = 0;
                  if (strtol(state.tmp.buffer, NiL, 8) == CPIO_MAGIC && strtol(state.tmp.buffer + f->st->st_size, NiL, 8) != CPIO_MAGIC)
                  {
                        f->st->st_size = 0;
                        if (!ap->warnlinkhead)
                        {
                              ap->warnlinkhead = 1;
                              error(1, "%s: compensating for invalid %s header hard link sizes", ap->name, ap->format->name);
                        }
                  }
            }
            return 1;
      case PAX_EVENT_DELTA_EXTEND:
            return 1;
      }
      return 0;
}

static int
asc_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
{
      unsigned int            magic;

      if (size >= ASC_HEADER && buf[0] == '0' && sfsscanf((char*)buf, "%6o", &magic) == 1 && magic == ASC_MAGIC)
            return init(ap);
      return 0;
}

static int
asc_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      Localstat_t lst;

      if (paxread(pax, ap, state.tmp.buffer, (off_t)0, (off_t)ASC_HEADER, 0) <= 0)
            return 0;
      state.tmp.buffer[ASC_HEADER] = 0;
      if (state.tmp.buffer[0] == '0' && sfsscanf(state.tmp.buffer, "%6o%8lx%8lx%8lx%8lx%8lx%8lx%8I*x%8lx%8lx%8lx%8lx%8x%8lx",
            &f->magic,
            &lst.ino,
            &lst.mode,
            &lst.uid,
            &lst.gid,
            &lst.nlink,
            &lst.mtime,
            sizeof(lst.size), &lst.size,
            &lst.dev_major,
            &lst.dev_minor,
            &lst.rdev_major,
            &lst.rdev_minor,
            &f->namesize,
            &lst.checksum) == 14 && f->magic == ASC_MAGIC)
      {
            f->checksum = lst.checksum;
            f->st->st_dev = makedev(lst.dev_major, lst.dev_minor);
            f->st->st_ino = lst.ino;
            f->st->st_mode = lst.mode;
            f->st->st_uid = lst.uid;
            f->st->st_gid = lst.gid;
            f->st->st_nlink = lst.nlink;
            IDEVICE(f->st, makedev(lst.rdev_major, lst.rdev_minor));
            f->st->st_mtime = lst.mtime;
            f->st->st_size = lst.size;
            return cpio_common(pax, ap, f, ASC_ALIGN, ASC_HEADER);
      }
      paxunread(pax, ap, state.tmp.buffer, ASC_HEADER);
      return 0;
}

static int
asc_putheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      int   n;

      if (state.complete)
            complete(ap, f, ASC_HEADER + f->namesize);
      if (ap->format->variant == ASC)
            f->checksum = 0;
      sfsprintf(state.tmp.buffer, state.tmp.buffersize, "%0.6lo%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx",
            (long)(ap->format->variant == ASC ? ASC_MAGIC : ASCHK_MAGIC),
            (long)f->st->st_ino,
            (long)f->st->st_mode,
            (long)f->st->st_uid,
            (long)f->st->st_gid,
            (long)f->st->st_nlink,
            (long)f->st->st_mtime,
            (long)f->st->st_size + (long)f->linkpathsize,
            (long)major(f->st->st_dev),
            (long)minor(f->st->st_dev),
            (long)major(idevice(f->st)),
            (long)minor(idevice(f->st)),
            (long)f->namesize,
            f->checksum);
      paxwrite(pax, ap, state.tmp.buffer, ASC_HEADER);
      paxwrite(pax, ap, f->name, f->namesize);
      if (n = (ASC_HEADER + f->namesize) % ASC_ALIGN)
            while (n++ < ASC_ALIGN)
                  paxwrite(pax, ap, "", 1);
      return 1;
}

static int
aschk_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
{
      unsigned int            magic;

      if (size >= ASC_HEADER && buf[0] == '0' && sfsscanf((char*)buf, "%6o", &magic) == 1 && magic == ASCHK_MAGIC)
            return init(ap);
      return 0;
}

static int
aschk_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      Localstat_t lst;

      if (paxread(pax, ap, state.tmp.buffer, (off_t)0, (off_t)ASC_HEADER, 0) <= 0)
            return 0;
      state.tmp.buffer[ASC_HEADER] = 0;
      if (state.tmp.buffer[0] == '0' && sfsscanf(state.tmp.buffer, "%6o%8lx%8lx%8lx%8lx%8lx%8lx%8I*x%8lx%8lx%8lx%8lx%8x%8lx",
            &f->magic,
            &lst.ino,
            &lst.mode,
            &lst.uid,
            &lst.gid,
            &lst.nlink,
            &lst.mtime,
            sizeof(lst.size), &lst.size,
            &lst.dev_major,
            &lst.dev_minor,
            &lst.rdev_major,
            &lst.rdev_minor,
            &f->namesize,
            &lst.checksum) == 14 && f->magic == ASCHK_MAGIC)
      {
            f->checksum = lst.checksum;
            f->st->st_dev = makedev(lst.dev_major, lst.dev_minor);
            f->st->st_ino = lst.ino;
            f->st->st_mode = lst.mode;
            f->st->st_uid = lst.uid;
            f->st->st_gid = lst.gid;
            f->st->st_nlink = lst.nlink;
            IDEVICE(f->st, makedev(lst.rdev_major, lst.rdev_minor));
            f->st->st_mtime = lst.mtime;
            f->st->st_size = lst.size;
            return cpio_common(pax, ap, f, ASC_ALIGN, ASC_HEADER);
      }
      paxunread(pax, ap, state.tmp.buffer, ASC_HEADER);
      return 0;
}

static unsigned long
aschk_checksum(Pax_t* pax, Archive_t* ap, File_t* f, void* ab, size_t n, register unsigned long sum)
{
      register unsigned char* b = (unsigned char*)ab;
      register unsigned char* e;

      e = b + n;
      while (b < e)
            sum += *b++;
      return sum;
}

/*
 * convert binary header shorts to long
 */

static long
binary_long(register unsigned short* s)
{
      Integral_t  u;

      u.l = 1;
      if (u.c[0])
      {
            u.s[0] = s[1];
            u.s[1] = s[0];
      }
      else
      {
            u.s[0] = s[0];
            u.s[1] = s[1];
      }
      return u.l;
}

/*
 * convert long to binary header shorts
 */

static void
binary_short(register unsigned short* s, long n)
{
      Integral_t  u;

      u.l = 1;
      if (u.c[0])
      {
            u.l = n;
            s[0] = u.s[1];
            s[1] = u.s[0];
      }
      else
      {
            u.l = n;
            s[0] = u.s[0];
            s[1] = u.s[1];
      }
}

static int
binary_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
{
      short       magic = CPIO_MAGIC;
      int         swap;

      if (size >= BINARY_HEADER && (swap = swapop(&magic, buf, 2)) >= 0)
      {
            ap->swap = swap;
            return init(ap);
      }
      return 0;
}

static int
binary_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      Binary_header_t   hdr;

      if (paxread(pax, ap, &hdr, (off_t)BINARY_HEADER, (off_t)BINARY_HEADER, 0) <= 0)
            return 0;
      if (ap->swap)
      {
            memcpy(state.tmp.buffer, &hdr, BINARY_HEADER);
            swapmem(ap->swap, &hdr, &hdr, BINARY_HEADER);
      }
      f->magic = hdr.magic;
      if (f->magic == CPIO_MAGIC)
      {
            f->namesize = hdr.namesize;
            f->st->st_dev = hdr.dev;
            f->st->st_ino = hdr.ino;
            f->st->st_mode = hdr.mode;
            f->st->st_uid = hdr.uid;
            f->st->st_gid = hdr.gid;
            f->st->st_nlink = hdr.links;
            IDEVICE(f->st, hdr.rdev);
            f->st->st_mtime = binary_long(hdr.mtime);
            f->st->st_size = binary_long(hdr.size);
            return cpio_common(pax, ap, f, CPIO_ALIGN, CPIO_HEADER);
      }
      paxunread(pax, ap, state.tmp.buffer, CPIO_HEADER);
      return 0;
}

static int
binary_putheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      Binary_header_t   hdr;
      int         n;

      if (state.complete)
            complete(ap, f, BINARY_HEADER + f->namesize);
      hdr.magic = CPIO_MAGIC;
      hdr.namesize = f->namesize;
      binary_short(hdr.size, f->st->st_size + (f->type == X_IFLNK ? f->linkpathsize : 0));
      hdr.dev = f->st->st_dev;
      hdr.ino = f->st->st_ino;
      hdr.mode = f->st->st_mode;
      hdr.uid = f->st->st_uid;
      hdr.gid = f->st->st_gid;
      hdr.links = f->st->st_nlink;
      hdr.rdev = idevice(f->st);
      if (hdr.rdev != idevice(f->st))
            error(1, "%s: special device numbers truncated", f->name);
      binary_short(hdr.mtime, (long)f->st->st_mtime);
      paxwrite(pax, ap, &hdr, BINARY_HEADER);
      paxwrite(pax, ap, f->name, f->namesize);
      if (n = (BINARY_HEADER + f->namesize) % BINARY_ALIGN)
            while (n++ < BINARY_ALIGN)
                  paxwrite(pax, ap, "", 1);
      if (f->type == X_IFLNK)
      {
            if (streq(f->name, f->linkpath))
                  error(1, "%s: symbolic link loops to self", f->name);
            paxwrite(pax, ap, f->linkpath, f->linkpathsize);
            putdeltaheader(ap, f);
      }
      return 1;
}

static int
binary_validate(Pax_t* pax, Archive_t* ap, File_t* f)
{
      if (f->namesize > (CPIO_NAMESIZE + 1))
      {
            error(2, "%s: file name too long", f->name);
            return 0;
      }
      return 1;
}

Format_t    pax_asc_format =
{
      "asc",
      0,
      "s5r4 extended cpio character",
      ASC,
      ARCHIVE|IN|OUT,
      DEFBUFFER,
      DEFBLOCKS,
      4,
      pax_asc_next,
      0,
      cpio_done,
      asc_getprologue,
      asc_getheader,
      0,
      0,
      cpio_getepilogue,
      cpio_putprologue,
      asc_putheader,
      0,
      0,
      cpio_putepilogue,
      0,
      0,
      0
};

Format_t    pax_aschk_format =
{
      "aschk",
      0,
      "s5r4 extended cpio character with checksum",
      ASCHK,
      ARCHIVE|IN|OUT,
      DEFBUFFER,
      DEFBLOCKS,
      4,
      pax_aschk_next,
      0,
      cpio_done,
      aschk_getprologue,
      aschk_getheader,
      0,
      0,
      cpio_getepilogue,
      cpio_putprologue,
      asc_putheader,
      0,
      0,
      cpio_putepilogue,
      0,
      0,
      aschk_checksum
};

Format_t    pax_binary_format =
{
      "binary",
      "binary-cpio",
      "cpio binary with symlinks",
      BINARY,
      ARCHIVE|IN|OUT,
      DEFBUFFER,
      DEFBLOCKS,
      2,
      pax_binary_next,
      0,
      cpio_done,
      binary_getprologue,
      binary_getheader,
      0,
      0,
      cpio_getepilogue,
      cpio_putprologue,
      binary_putheader,
      0,
      0,
      cpio_putepilogue,
      0,
      0,
      0,
      binary_validate
};

Format_t    pax_cpio_format =
{
      "cpio",
      0,
      "cpio character with symlinks",
      CPIO,
      ARCHIVE|IN|OUT,
      DEFBUFFER,
      DEFBLOCKS,
      0,
      PAXNEXT(pax_cpio_next),
      0,
      cpio_done,
      cpio_getprologue,
      cpio_getheader,
      0,
      0,
      cpio_getepilogue,
      cpio_putprologue,
      cpio_putheader,
      0,
      0,
      cpio_putepilogue,
      0,
      0,
      0,
      0,
      cpio_event,
      PAX_EVENT_BUG_19951031|PAX_EVENT_DELTA_EXTEND
};

PAXLIB(&pax_cpio_format)

Generated by  Doxygen 1.6.0   Back to index