#include "zebra.h" #include /* for FILE */ #include /* for size_t */ #include "pack2b.h" #include /* for memmove() */ #include /* for uint8_t, etc. */ #include /* for strerror(), etc. */ char zebra_err[256]; zebraFile *zebra_open(const char *filename) { FILE *f = fopen(filename, "r"); if (!f) { sprintf(zebra_err, "failed to open '%s': %s", filename, strerror(errno)); return NULL; } zebraFile *z = (zebraFile *) malloc(sizeof(zebraFile)); z->f = f; z->offset = 0; z->lr_size = 0; z->buf = NULL; z->buf_size = 0; return z; } int read_next_physical_record(zebraFile *z) { /* Read the next physical record from the zebra file and append it to the * buffer. * * Returns 0 on success, -1 on error, and 1 on EOF. */ uint8_t buf[48]; size_t nbytes; uint32_t s0, s1, s2, s3, nwphr, nfast; nbytes = fread(buf,4,8,z->f); if (nbytes == 0) return 1; if (nbytes != 8) { sprintf(zebra_err, "expected %i words but only read %zu", 8, nbytes); return -1; } s0 = unpacki32(buf); s1 = unpacki32(buf+4*1); s2 = unpacki32(buf+4*2); s3 = unpacki32(buf+4*3); nwphr = unpacki32(buf+4*4); nfast = unpacki32(buf+7*4); if (nwphr & (ZEBRA_EMERGENCY_STOP | ZEBRA_END_OF_RUN)) return 1; nwphr &= ZEBRA_BLOCK_SIZE_MASK; uint32_t words = nwphr*(1 + nfast) - 8; if (s0 != ZEBRA_SIG0) { sprintf(zebra_err, "invalid steering block stamp 0x%08x", s0); return -1; } if (s1 != ZEBRA_SIG1) { sprintf(zebra_err, "invalid steering block stamp 0x%08x", s1); return -1; } if (s2 != ZEBRA_SIG2) { sprintf(zebra_err, "invalid steering block stamp 0x%08x", s2); return -1; } if (s3 != ZEBRA_SIG3) { sprintf(zebra_err, "invalid steering block stamp 0x%08x", s3); return -1; } z->buf = realloc(z->buf, z->buf_size+words*4); nbytes = fread(z->buf+z->buf_size, 4, words, z->f); z->buf_size += words*4; if (nbytes != words) { sprintf(zebra_err, "expected %i words but only read %zu", words, nbytes); return -1; } return 0; } int get_bytes(zebraFile *z, size_t size) { /* Read bytes from the zdab file until there are at least `size` words in * the buffer. * * Returns 0 on success, -1 on error, and 1 on EOF. */ int rv; while ((z->buf_size - z->offset) < size*4) { rv = read_next_physical_record(z); if (rv == -1) { return -1; } else if (z->buf_size == 0 && rv == 1) { /* EOF and there are no bytes left. */ return 1; } } return 0; } int read_next_logical_record(zebraFile *z) { /* Read the next logical record into the buffer. * * Returns 0 on success, -1 on error, and 1 on EOF. */ uint32_t size, type, nwtx, nwseg, nwtab, nwuh; while (1) { memmove(z->buf,z->buf+z->offset,z->buf_size-z->offset); z->buf = realloc(z->buf, z->buf_size-z->offset); z->buf_size -= z->offset; z->offset = 0; switch (get_bytes(z,1)) { case 1: return 1; case -1: return -1; } size = unpacki32(z->buf+z->offset); z->offset += 4; if (size == 0) continue; switch (get_bytes(z,1)) { case 1: return 1; case -1: return -1; } type = unpacki32(z->buf+z->offset); z->offset += 4; switch (type) { case 5: case 6: get_bytes(z,size-1); z->offset += (size-1)*4; continue; case 1: get_bytes(z,size); z->offset += size*4; continue; } z->lr_size = (size + 2)*4; get_bytes(z,size); nwtx = unpacki32(z->buf+z->offset+4*4); nwseg = unpacki32(z->buf+z->offset+5*4); nwtab = unpacki32(z->buf+z->offset+6*4); nwuh = unpacki32(z->buf+z->offset+9*4); z->offset += 10*4; z->offset += nwtx*4; z->offset += nwseg*4; z->offset += nwtab*4; z->offset += nwuh*4; break; } return 0; } int next_bank(zebraFile *z, bank *b) { int rv; uint32_t io, noff; if (z->offset == z->lr_size) { rv = read_next_logical_record(z); if (rv) return rv; } io = unpacki32(z->buf+z->offset); z->offset += 4; noff = io & 0xFFFF; if (noff > 12) { z->offset += (noff-12)*4; } unpack(z->buf+z->offset,"lllllllll",&b->next, &b->up, &b->orig, &b->number, &b->name, &b->num_links, &b->num_structural_links, &b->num_data_words, &b->status); z->offset += 9*4; b->data = (uint32_t *) (z->buf+z->offset); z->offset += b->num_data_words*4; return 0; } void zebra_close(zebraFile *z) { fclose(z->f); if (z->buf) free(z->buf); free(z); }