/*********************************************************************** * * * 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 pds format */ #include "format.h" #include <tm.h> typedef struct Pdsdir_s { char* link; unsigned long block; time_t time; char name[9]; } Pdsdir_t; typedef struct Pds_s { char* format; unsigned char* map; size_t index; size_t size; Pdsdir_t dir[1]; } Pds_t; static int pds_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size) { register Pds_t* pds; register unsigned char* b; register unsigned char* e; register size_t n; register size_t i; register size_t m; size_t links; if (size < 256 || buf[0] != 0) return 0; b = buf; e = b + b[1]; while (b != e) { n = 12 + 2 * (b[11] & 0x1f); if ((e - b) < n) return 0; b += n; } i = 0; m = 32; if (!(pds = newof(0, Pds_t, 1, (m - 1) * sizeof(Pdsdir_t)))) nospace(); pds->map = ccmap(CC_EBCDIC_O, CC_NATIVE); links = 0; while ((b = (unsigned char*)paxget(pax, ap, -256, NiL)) && !b[0]) { n = b[1]; b += 2; e = b + n; while ((e - b) >= 12) { if (b[0] == 0xff && !memcmp(b, "\xff\xff\xff\xff\xff\xff\xff\xff", 8)) goto done; n = 12 + 2 * (b[11] & 0x1f); if ((e - b) < n) break; if (i >= m) { m += 32; if (!(pds = newof(pds, Pds_t, 1, (m - 1) * sizeof(Pdsdir_t)))) nospace(); } memcpy(pds->dir[i].name, b, 8); ccmapstr(pds->map, pds->dir[i].name, 8); pds->dir[i].block = (b[8] << 16) | (b[9] << 8) | b[10]; pds->dir[i].time = (n > 25) ? tmscan(sfprints("%02x %02x%01x %02x %02x", b[21], b[22], b[23] >> 4, b[24], b[25]), NiL, "%y %j %H %M", NiL, NiL, 0) : NOW; if (b[11] & 0x80) { links++; pds->dir[i].link = &pds->dir[i].name[0]; } else pds->dir[i].link = 0; b += n; for (n = 8; n > 0 && pds->dir[i].name[n - 1] == ' '; n--); pds->dir[i].name[n] = 0; i++; } } done: pds->size = i; m = 0; while (links > 0) { while (!pds->dir[m].link) m++; for (n = 0; n < i; n++) if (n != m && pds->dir[n].block == pds->dir[m].block) break; if (n < m) { pds->dir[n].link = pds->dir[m].name; pds->dir[m].link = 0; } else if (n < i) pds->dir[m].link = pds->dir[n].name; else pds->dir[m].link = 0; m++; links--; } pds->format = pax_pds_format.name; ap->data = pds; return 1; } static int pds_done(Pax_t* pax, register Archive_t* ap) { if (ap->data) { free(ap->data); ap->data = 0; } return 0; } static int pds_getheader(Pax_t* pax, register Archive_t* ap, register File_t* f) { register Pds_t* pds = (Pds_t*)ap->data; register Pdsdir_t* dp; if (pds->index >= pds->size) return 0; dp = pds->dir + pds->index++; f->name = dp->name; f->linkpath = dp->link; f->st->st_atime = f->st->st_mtime = dp->time; f->st->st_dev = 0; f->st->st_ino = 0; f->st->st_mode = X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IROTH; f->st->st_uid = state.uid; f->st->st_gid = state.gid; f->st->st_nlink = 1; IDEVICE(f->st, 0); f->st->st_size = dp->block; return 1; } static int pds_getdata(Pax_t* pax, register Archive_t* ap, register File_t* f, int wfd) { return 1; } Format_t pax_pds_format = { "pds", 0, "mvs partitioned dataset", 0, ARCHIVE|NOHARDLINKS, DEFBUFFER, DEFBLOCKS, 0, PAXNEXT(pax_pds_next), 0, pds_done, pds_getprologue, pds_getheader, pds_getdata, }; PAXLIB(&pax_pds_format)