mirror of
https://github.com/open-simh/simtools.git
synced 2026-01-31 22:03:45 +00:00
Also add more checks to RT11 MLB reader.
This commit is contained in:
100
mlb-rt11.c
100
mlb-rt11.c
@@ -40,13 +40,12 @@ DAMAGE.
|
||||
#include <string.h>
|
||||
|
||||
#include "rad50.h"
|
||||
|
||||
#include "stream2.h"
|
||||
|
||||
#include "mlb.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#define MLBDEBUG_OPEN 0
|
||||
|
||||
static MLB *mlb_rt11_open(
|
||||
char *name,
|
||||
int allow_object_library);
|
||||
@@ -73,6 +72,9 @@ struct mlb_vtbl mlb_rt11_vtbl = {
|
||||
*
|
||||
* A MLB Macro Library Header differs a lot from an Object Library Header.
|
||||
*/
|
||||
|
||||
#define BLOCKSIZE 512
|
||||
|
||||
#define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8))
|
||||
|
||||
/* BYTEPOS calculates the byte position within the macro libray file.
|
||||
@@ -80,7 +82,8 @@ struct mlb_vtbl mlb_rt11_vtbl = {
|
||||
be able to calculate the entries' sizes, which isn't actually
|
||||
stored in the directory. */
|
||||
|
||||
#define BYTEPOS(rec) ((WORD((rec)+4) & 32767) * 512 + (WORD((rec)+6) & 511))
|
||||
#define BYTEPOS(rec) ((WORD((rec)+4) & 32767) * BLOCKSIZE + \
|
||||
(WORD((rec)+6) & 511))
|
||||
|
||||
/* compare_position is the qsort callback function that compares byte
|
||||
locations within the macro library */
|
||||
@@ -124,6 +127,9 @@ MLB *mlb_rt11_open(
|
||||
unsigned start_block;
|
||||
int i;
|
||||
|
||||
#if MLBDEBUG_OPEN
|
||||
fprintf(stderr, "mlb_rt11_open('%s', %d)\n", name, allow_object_library);
|
||||
#endif
|
||||
(void)allow_object_library; /* This parameter is not supported */
|
||||
mlb->vtbl = &mlb_rt11_vtbl;
|
||||
mlb->directory = NULL;
|
||||
@@ -137,14 +143,12 @@ MLB *mlb_rt11_open(
|
||||
buff = memcheck(malloc(044)); /* Size of MLB library header */
|
||||
|
||||
if (fread(buff, 1, 044, mlb->fp) < 044) {
|
||||
mlb_rt11_close(mlb);
|
||||
free(buff);
|
||||
return NULL;
|
||||
goto error; /* Nope. */
|
||||
}
|
||||
|
||||
if (WORD(buff) != 01001) { /* Is this really a macro library? */
|
||||
mlb_rt11_close(mlb); /* Nope. */
|
||||
return NULL;
|
||||
if (WORD(buff) != 01001 ||
|
||||
WORD(buff + 2) != 0500) { /* Is this really a macro library? */
|
||||
goto error; /* Nope. */
|
||||
}
|
||||
|
||||
entsize = WORD(buff + 032); /* The size of each macro directory
|
||||
@@ -153,17 +157,34 @@ MLB *mlb_rt11_open(
|
||||
start_block = WORD(buff + 034); /* The start RT-11 block of the
|
||||
directory */
|
||||
|
||||
if (entsize < 8) { /* Is this really a macro library? */
|
||||
fprintf(stderr, "mlb_rt11_open error: entsize too small: %d\n", entsize);
|
||||
goto error; /* Nope. */
|
||||
}
|
||||
|
||||
if (start_block < 1) { /* Is this really a macro library? */
|
||||
fprintf(stderr, "mlb_rt11_open error: start_block too small: %d\n", start_block);
|
||||
goto error; /* Nope. */
|
||||
}
|
||||
|
||||
#if MLBDEBUG_OPEN
|
||||
fprintf(stderr, "entsize=%d, nr_entries=%d, start_block=%d\n",
|
||||
entsize, nr_entries, start_block);
|
||||
#endif
|
||||
free(buff); /* Done with that header. */
|
||||
|
||||
/* Allocate a buffer for the disk directory */
|
||||
buff = memcheck(malloc(nr_entries * entsize));
|
||||
fseek(mlb->fp, start_block * 512, SEEK_SET); /* Go to the directory */
|
||||
/* Go to the directory */
|
||||
if (fseek(mlb->fp, start_block * BLOCKSIZE, SEEK_SET) == -1) {
|
||||
fprintf(stderr, "mlb_rt11_open error: seek error: %d\n", start_block * BLOCKSIZE);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Read the disk directory */
|
||||
if (fread(buff, entsize, nr_entries, mlb->fp) < nr_entries) {
|
||||
mlb_rt11_close(mlb); /* Sorry, read error. */
|
||||
free(buff);
|
||||
return NULL;
|
||||
fprintf(stderr, "mlb_rt11_open error: fread: not enough entries\n");
|
||||
goto error; /* Sorry, read error. */
|
||||
}
|
||||
|
||||
/* Shift occupied directory entries to the front of the array
|
||||
@@ -174,11 +195,14 @@ MLB *mlb_rt11_open(
|
||||
for (i = 0, j = nr_entries; i < j; i++) {
|
||||
char *ent1,
|
||||
*ent2;
|
||||
int w1, w2;
|
||||
|
||||
ent1 = buff + (i * entsize);
|
||||
w1 = WORD(ent1);
|
||||
w2 = WORD(ent1 + 2);
|
||||
/* Unused entries have 0177777 0177777 for the RAD50 name,
|
||||
which is not legal RAD50. */
|
||||
if (WORD(ent1) == 0177777 && WORD(ent1 + 2) == 0177777) {
|
||||
if (w1 == 0177777 && w2 == 0177777) {
|
||||
while (--j > i
|
||||
&& (ent2 = buff + (j * entsize), WORD(ent2) == 0177777 && WORD(ent2 + 2) == 0177777)) ;
|
||||
if (j <= i)
|
||||
@@ -187,12 +211,24 @@ MLB *mlb_rt11_open(
|
||||
into unused entry's
|
||||
space */
|
||||
memset(ent2, 0377, entsize); /* Mark entry unused */
|
||||
} else {
|
||||
if (w1 == 0000000 && w2 == 0000000) {
|
||||
fprintf(stderr, "mlb_rt11_open error: bad file, null name\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now i contains the actual number of entries. */
|
||||
|
||||
mlb->nentries = i;
|
||||
#if MLBDEBUG_OPEN
|
||||
fprintf(stderr, "mlb->nentries=%d\n", mlb->nentries);
|
||||
#endif
|
||||
if (mlb->nentries == 0) {
|
||||
fprintf(stderr, "mlb_rt11_open error: no entries\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Sort the array by file position */
|
||||
|
||||
@@ -202,6 +238,11 @@ MLB *mlb_rt11_open(
|
||||
mlb->directory = memcheck(malloc(sizeof(MLBENT) * mlb->nentries));
|
||||
memset(mlb->directory, 0, sizeof(MLBENT) * mlb->nentries);
|
||||
|
||||
unsigned long max_filepos;
|
||||
|
||||
fseek(mlb->fp, 0, SEEK_END);
|
||||
max_filepos = ftell(mlb->fp);
|
||||
|
||||
/* Build in-memory directory */
|
||||
for (j = 0; j < i; j++) {
|
||||
char radname[16];
|
||||
@@ -214,17 +255,25 @@ MLB *mlb_rt11_open(
|
||||
radname[6] = 0;
|
||||
|
||||
trim(radname);
|
||||
if (radname[0] == '\0' || strchr(radname, ' ')) {
|
||||
fprintf(stderr, "mlb_rt11_open error: entry with space in name\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
mlb->directory[j].label = memcheck(strdup(radname));
|
||||
mlb->directory[j].position = BYTEPOS(ent);
|
||||
|
||||
if (mlb->directory[j].position > max_filepos) {
|
||||
fprintf(stderr, "mlb_rt11_open error: entry past EOF\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (j < i - 1) {
|
||||
mlb->directory[j].length = BYTEPOS(ent + entsize) - BYTEPOS(ent);
|
||||
} else {
|
||||
unsigned long max;
|
||||
unsigned long max = max_filepos;
|
||||
char c;
|
||||
|
||||
fseek(mlb->fp, 0, SEEK_END);
|
||||
max = ftell(mlb->fp);
|
||||
/* Look for last non-zero */
|
||||
do {
|
||||
max--;
|
||||
@@ -234,6 +283,13 @@ MLB *mlb_rt11_open(
|
||||
max++;
|
||||
mlb->directory[j].length = max - BYTEPOS(ent);
|
||||
}
|
||||
#if MLBDEBUG_OPEN
|
||||
fprintf(stderr, "entry #%d '%s' %ld length %d\n",
|
||||
j,
|
||||
mlb->directory[j].label,
|
||||
mlb->directory[j].position,
|
||||
mlb->directory[j].length);
|
||||
#endif
|
||||
}
|
||||
|
||||
free(buff);
|
||||
@@ -241,6 +297,14 @@ MLB *mlb_rt11_open(
|
||||
|
||||
/* Done. Return the struct that represents the opened MLB. */
|
||||
return mlb;
|
||||
|
||||
error:
|
||||
#if MLBDEBUG_OPEN
|
||||
fprintf(stderr, "(mlb_rt11_open closing '%s' due to errors)\n", name);
|
||||
#endif
|
||||
mlb_rt11_close(mlb); /* Sorry, bad file. */
|
||||
free(buff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mlb_rt11_close discards MLB and closes the file. */
|
||||
|
||||
Reference in New Issue
Block a user