Fixed a known issue in which the output of "vendor" (read-only) GDS
can become corrupted if the name of the cell in magic changes from the name of the structure in GDS pointed to by the GDS_FILE property, and the new name is a different length from the original name. Fixed by Claude Fable 5 and checked for all name-change scenarios for both compressed and uncompressed output.
This commit is contained in:
parent
4b39363a3b
commit
443045b331
|
|
@ -347,7 +347,7 @@ CalmaWrite(
|
|||
* to insure that each child cell is output before it is used. The
|
||||
* root cell is output last.
|
||||
*/
|
||||
calmaProcessDef(rootDef, f, CalmaDoLibrary);
|
||||
good = (calmaProcessDef(rootDef, f, CalmaDoLibrary) == 0) ? TRUE : FALSE;
|
||||
|
||||
/*
|
||||
* Check for any cells that were instanced in the output definition
|
||||
|
|
@ -366,7 +366,10 @@ CalmaWrite(
|
|||
|
||||
extraDef = DBCellLookDef((char *)he->h_key.h_name);
|
||||
if (extraDef != NULL)
|
||||
calmaProcessDef(extraDef, f, FALSE);
|
||||
{
|
||||
if (calmaProcessDef(extraDef, f, FALSE) != 0)
|
||||
good = FALSE;
|
||||
}
|
||||
else
|
||||
TxError("Error: Cell %s is not defined in the output file!\n",
|
||||
refname + 1);
|
||||
|
|
@ -376,7 +379,7 @@ CalmaWrite(
|
|||
/* Finish up by outputting the end-of-library marker */
|
||||
calmaOutRH(4, CALMA_ENDLIB, CALMA_NODATA, f);
|
||||
fflush(f);
|
||||
good = !ferror(f);
|
||||
if (ferror(f)) good = FALSE;
|
||||
|
||||
/* See if any problems occurred */
|
||||
if ((problems = (DBWFeedbackCount - oldCount)))
|
||||
|
|
@ -975,11 +978,10 @@ calmaProcessDef(
|
|||
|
||||
if (isReadOnly && hasContent)
|
||||
{
|
||||
char *buffer, *offptr, *retfilename;
|
||||
char *buffer, *retfilename;
|
||||
size_t defsize, numbytes;
|
||||
off_t cellstart, cellend, structstart;
|
||||
off_t cellstart, cellend;
|
||||
dlong cval;
|
||||
int namelen;
|
||||
FILETYPE fi;
|
||||
|
||||
/* Give some feedback to the user */
|
||||
|
|
@ -1039,72 +1041,109 @@ calmaProcessDef(
|
|||
cellend = (off_t)cval;
|
||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||
if (!oldStyle)
|
||||
{
|
||||
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
||||
/* Output structure header */
|
||||
calmaOutRH(28, CALMA_BGNSTR, CALMA_I2, outf);
|
||||
if (CalmaDateStamp != NULL)
|
||||
calmaOutDate(*CalmaDateStamp, outf);
|
||||
else
|
||||
calmaOutDate(def->cd_timestamp, outf);
|
||||
calmaOutDate(time((time_t *) 0), outf);
|
||||
|
||||
/* Name structure the same as the magic cellname */
|
||||
calmaOutStructName(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
cellstart = (off_t)cval;
|
||||
|
||||
/* GDS_START has been defined as the start of data after the cell */
|
||||
/* structure name. However, a sanity check is wise, so move back */
|
||||
/* that far and make sure the structure name is there. */
|
||||
structstart = cellstart - (off_t)(strlen(def->cd_name));
|
||||
if (strlen(def->cd_name) & 0x1) structstart--;
|
||||
structstart -= 2;
|
||||
/* Sanity check: The structure must be long enough to */
|
||||
/* hold at least an ENDSTR record. */
|
||||
|
||||
FSEEK(fi, structstart, SEEK_SET);
|
||||
|
||||
/* Read the structure name and check against the CellDef name */
|
||||
defsize = (size_t)(cellstart - structstart);
|
||||
buffer = (char *)mallocMagic(defsize + 1);
|
||||
numbytes = magicFREAD(buffer, sizeof(char), (size_t)defsize, fi);
|
||||
if (numbytes == defsize)
|
||||
{
|
||||
buffer[defsize] = '\0';
|
||||
if (buffer[0] != 0x06 || buffer[1] != 0x06)
|
||||
{
|
||||
TxError("Calma output error: Structure name not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n", cellstart);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else if (strcmp(&buffer[2], def->cd_name))
|
||||
{
|
||||
TxError("Calma output warning: Structure definition has name"
|
||||
" %s but cell definition has name %s.\n",
|
||||
&buffer[2], def->cd_name);
|
||||
TxError("The structure definition will be given the cell name.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Calma output error: Can't read cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
freeMagic(buffer);
|
||||
|
||||
if (cellend < cellstart) /* Sanity check */
|
||||
if (cellend < cellstart + 4)
|
||||
{
|
||||
TxError("Calma output error: Bad vendor GDS file reference!\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
|
||||
if (isReadOnly && !oldStyle)
|
||||
{
|
||||
/* GDS_START has been defined as the start of data after the */
|
||||
/* cell structure name. A sanity check is wise, so search */
|
||||
/* backward from that position for the STRNAME record header. */
|
||||
/* Note that the length of the structure name in the file */
|
||||
/* cannot be assumed to be the length of the cell name in */
|
||||
/* magic, because the cell may have been renamed after the */
|
||||
/* GDS file was read. */
|
||||
|
||||
off_t blockstart;
|
||||
size_t blocksize;
|
||||
int reclen;
|
||||
char *sptr = NULL;
|
||||
|
||||
blockstart = cellstart - (off_t)CALMARECORDMAX;
|
||||
if (blockstart < 0) blockstart = (off_t)0;
|
||||
blocksize = (size_t)(cellstart - blockstart);
|
||||
|
||||
FSEEK(fi, blockstart, SEEK_SET);
|
||||
buffer = (char *)mallocMagic(blocksize + 1);
|
||||
numbytes = magicFREAD(buffer, sizeof(char), blocksize, fi);
|
||||
if (numbytes == blocksize)
|
||||
{
|
||||
buffer[blocksize] = '\0';
|
||||
|
||||
/* Scan candidate record lengths from shortest to longest. */
|
||||
/* A structure name contains only printable characters, so */
|
||||
/* the first match found is the STRNAME record header. */
|
||||
|
||||
for (reclen = 6; reclen <= (int)blocksize; reclen += 2)
|
||||
{
|
||||
char *tptr = buffer + blocksize - reclen;
|
||||
if (((unsigned char)tptr[0] == (unsigned char)(reclen >> 8))
|
||||
&& ((unsigned char)tptr[1] == (unsigned char)(reclen & 0xff))
|
||||
&& (tptr[2] == CALMA_STRNAME)
|
||||
&& (tptr[3] == CALMA_ASCII))
|
||||
{
|
||||
sptr = tptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sptr == NULL)
|
||||
{
|
||||
TxError("Calma output error: Structure name not found"
|
||||
" ending at GDS file position %"DLONG_PREFIX"d\n",
|
||||
(dlong)cellstart);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else if (strcmp(sptr + 4, def->cd_name))
|
||||
{
|
||||
TxError("Calma output warning: Structure definition has name"
|
||||
" %s but cell definition has name %s.\n",
|
||||
sptr + 4, def->cd_name);
|
||||
TxError("The structure definition will be given the cell name.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Calma output error: Can't read cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
freeMagic(buffer);
|
||||
}
|
||||
else if (isReadOnly)
|
||||
{
|
||||
/* Old-style GDS_BEGIN points to the start of the structure */
|
||||
/* (BGNSTR record), which is copied verbatim including the */
|
||||
/* structure name; check that the BGNSTR record is there. */
|
||||
|
||||
char header[4];
|
||||
|
||||
FSEEK(fi, cellstart, SEEK_SET);
|
||||
numbytes = magicFREAD(header, sizeof(char), 4, fi);
|
||||
if ((numbytes != 4) || (header[2] != CALMA_BGNSTR)
|
||||
|| (header[3] != CALMA_I2))
|
||||
{
|
||||
TxError("Calma output error: Structure definition not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n",
|
||||
(dlong)cellstart);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (isReadOnly)
|
||||
{
|
||||
/* Important note: mallocMagic() is limited to size integer. */
|
||||
/* This will fail on a structure larger than ~2GB. */
|
||||
|
|
@ -1112,46 +1151,74 @@ calmaProcessDef(
|
|||
defsize = (size_t)(cellend - cellstart);
|
||||
buffer = (char *)mallocMagic(defsize);
|
||||
|
||||
FSEEK(fi, cellstart, SEEK_SET);
|
||||
numbytes = magicFREAD(buffer, sizeof(char), (size_t)defsize, fi);
|
||||
|
||||
if (numbytes == defsize)
|
||||
{
|
||||
/* Sanity check: buffer must end with a structure */
|
||||
/* definition end (record 0x07). */
|
||||
|
||||
if (buffer[defsize - 4] != 0x00 ||
|
||||
buffer[defsize - 3] != 0x04 ||
|
||||
buffer[defsize - 2] != 0x07 ||
|
||||
buffer[defsize - 1] != 0x00)
|
||||
{
|
||||
TxError("Calma output error: Structure end definition not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n", cellend);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
numbytes = fwrite(buffer, sizeof(char), (size_t)defsize, outf);
|
||||
if (numbytes <= 0)
|
||||
{
|
||||
TxError("Calma output error: Can't write cell from "
|
||||
"vendor GDS. Using magic's internal "
|
||||
"definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (numbytes != defsize)
|
||||
{
|
||||
TxError("Calma output error: Can't read cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
|
||||
/* Additional information as to why data did not match */
|
||||
TxError("Size of data requested: %"DLONG_PREFIX"d", defsize);
|
||||
TxError("Length of data read: %"DLONG_PREFIX"d", numbytes);
|
||||
TxError("Size of data requested: %"DLONG_PREFIX"d", (dlong)defsize);
|
||||
TxError("Length of data read: %"DLONG_PREFIX"d", (dlong)numbytes);
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else if (buffer[defsize - 4] != 0x00 ||
|
||||
buffer[defsize - 3] != 0x04 ||
|
||||
buffer[defsize - 2] != 0x07 ||
|
||||
buffer[defsize - 1] != 0x00)
|
||||
{
|
||||
/* Sanity check: buffer must end with a structure */
|
||||
/* definition end (record 0x07). */
|
||||
|
||||
TxError("Calma output error: Structure end definition not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n", cellend);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All sanity checks have passed, so the structure header, */
|
||||
/* name, and data can be written. Nothing may be written */
|
||||
/* to the output before this point, so that a failed check */
|
||||
/* above falls back on the cell definition in magic without */
|
||||
/* leaving a partial structure in the output. */
|
||||
|
||||
if (!oldStyle)
|
||||
{
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
||||
/* Output structure header */
|
||||
calmaOutRH(28, CALMA_BGNSTR, CALMA_I2, outf);
|
||||
if (CalmaDateStamp != NULL)
|
||||
calmaOutDate(*CalmaDateStamp, outf);
|
||||
else
|
||||
calmaOutDate(def->cd_timestamp, outf);
|
||||
calmaOutDate(time((time_t *) 0), outf);
|
||||
|
||||
/* Name structure the same as the magic cellname */
|
||||
calmaOutStructName(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
numbytes = fwrite(buffer, sizeof(char), (size_t)defsize, outf);
|
||||
if (numbytes != defsize)
|
||||
{
|
||||
/* The structure header has already been written, so */
|
||||
/* it is not possible to fall back on the internal */
|
||||
/* cell definition; the output is corrupt and the */
|
||||
/* error is fatal. */
|
||||
|
||||
TxError("Calma output error: Failed to write cell \"%s\""
|
||||
" from vendor GDS. Output is invalid!\n",
|
||||
def->cd_name);
|
||||
freeMagic(buffer);
|
||||
FCLOSE(fi);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
freeMagic(buffer);
|
||||
}
|
||||
FCLOSE(fi);
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ CalmaWriteZ(
|
|||
* to insure that each child cell is output before it is used. The
|
||||
* root cell is output last.
|
||||
*/
|
||||
calmaProcessDefZ(rootDef, f, CalmaDoLibrary);
|
||||
good = (calmaProcessDefZ(rootDef, f, CalmaDoLibrary) == 0) ? TRUE : FALSE;
|
||||
|
||||
/*
|
||||
* Check for any cells that were instanced in the output definition
|
||||
|
|
@ -345,7 +345,10 @@ CalmaWriteZ(
|
|||
|
||||
extraDef = DBCellLookDef((char *)he->h_key.h_name);
|
||||
if (extraDef != NULL)
|
||||
calmaProcessDefZ(extraDef, f, FALSE);
|
||||
{
|
||||
if (calmaProcessDefZ(extraDef, f, FALSE) != 0)
|
||||
good = FALSE;
|
||||
}
|
||||
else
|
||||
TxError("Error: Cell %s is not defined in the output file!\n",
|
||||
refname + 1);
|
||||
|
|
@ -356,7 +359,7 @@ CalmaWriteZ(
|
|||
calmaOutRHZ(4, CALMA_ENDLIB, CALMA_NODATA, f);
|
||||
gzflush(f, Z_SYNC_FLUSH);
|
||||
gzerror(f, &nerr);
|
||||
good = (nerr == 0) ? TRUE : FALSE;
|
||||
if (nerr != 0) good = FALSE;
|
||||
|
||||
/* See if any problems occurred */
|
||||
if ((problems = (DBWFeedbackCount - oldCount)))
|
||||
|
|
@ -928,11 +931,10 @@ calmaProcessDefZ(
|
|||
|
||||
if (isReadOnly && hasContent)
|
||||
{
|
||||
char *buffer, *offptr, *retfilename;
|
||||
char *buffer, *retfilename;
|
||||
size_t defsize, numbytes;
|
||||
z_off_t cellstart, cellend, structstart;
|
||||
z_off_t cellstart, cellend;
|
||||
dlong cval;
|
||||
int namelen;
|
||||
gzFile fi;
|
||||
|
||||
/* Use PaOpen() so the paths searched are the same as were */
|
||||
|
|
@ -989,72 +991,109 @@ calmaProcessDefZ(
|
|||
cellend = (z_off_t)cval;
|
||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||
if (!oldStyle)
|
||||
{
|
||||
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
||||
/* Output structure header */
|
||||
calmaOutRHZ(28, CALMA_BGNSTR, CALMA_I2, outf);
|
||||
if (CalmaDateStamp != NULL)
|
||||
calmaOutDateZ(*CalmaDateStamp, outf);
|
||||
else
|
||||
calmaOutDateZ(def->cd_timestamp, outf);
|
||||
calmaOutDateZ(time((time_t *) 0), outf);
|
||||
|
||||
/* Name structure the same as the magic cellname */
|
||||
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
cellstart = (z_off_t)cval;
|
||||
|
||||
/* GDS_START has been defined as the start of data after the cell */
|
||||
/* structure name. However, a sanity check is wise, so move back */
|
||||
/* that far and make sure the structure name is there. */
|
||||
structstart = cellstart - (z_off_t)(strlen(def->cd_name));
|
||||
if (strlen(def->cd_name) & 0x1) structstart--;
|
||||
structstart -= 2;
|
||||
/* Sanity check: The structure must be long enough to */
|
||||
/* hold at least an ENDSTR record. */
|
||||
|
||||
gzseek(fi, structstart, SEEK_SET);
|
||||
|
||||
/* Read the structure name and check against the CellDef name */
|
||||
defsize = (size_t)(cellstart - structstart);
|
||||
buffer = (char *)mallocMagic(defsize + 1);
|
||||
numbytes = gzread(fi, buffer, sizeof(char) * (size_t)defsize);
|
||||
if (numbytes == defsize)
|
||||
{
|
||||
buffer[defsize] = '\0';
|
||||
if (buffer[0] != 0x06 || buffer[1] != 0x06)
|
||||
{
|
||||
TxError("Calma output error: Structure name not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n", cellstart);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else if (strcmp(&buffer[2], def->cd_name))
|
||||
{
|
||||
TxError("Calma output warning: Structure definition has name"
|
||||
" %s but cell definition has name %s.\n",
|
||||
&buffer[2], def->cd_name);
|
||||
TxError("The structure definition will be given the cell name.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Calma output error: Can't read cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
freeMagic(buffer);
|
||||
|
||||
if (cellend < cellstart) /* Sanity check */
|
||||
if (cellend < cellstart + 4)
|
||||
{
|
||||
TxError("Calma output error: Bad vendor GDS file reference!\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
|
||||
if (isReadOnly && !oldStyle)
|
||||
{
|
||||
/* GDS_START has been defined as the start of data after the */
|
||||
/* cell structure name. A sanity check is wise, so search */
|
||||
/* backward from that position for the STRNAME record header. */
|
||||
/* Note that the length of the structure name in the file */
|
||||
/* cannot be assumed to be the length of the cell name in */
|
||||
/* magic, because the cell may have been renamed after the */
|
||||
/* GDS file was read. */
|
||||
|
||||
z_off_t blockstart;
|
||||
size_t blocksize;
|
||||
int reclen;
|
||||
char *sptr = NULL;
|
||||
|
||||
blockstart = cellstart - (z_off_t)CALMARECORDMAX;
|
||||
if (blockstart < 0) blockstart = (z_off_t)0;
|
||||
blocksize = (size_t)(cellstart - blockstart);
|
||||
|
||||
gzseek(fi, blockstart, SEEK_SET);
|
||||
buffer = (char *)mallocMagic(blocksize + 1);
|
||||
numbytes = gzread(fi, buffer, sizeof(char) * blocksize);
|
||||
if (numbytes == blocksize)
|
||||
{
|
||||
buffer[blocksize] = '\0';
|
||||
|
||||
/* Scan candidate record lengths from shortest to longest. */
|
||||
/* A structure name contains only printable characters, so */
|
||||
/* the first match found is the STRNAME record header. */
|
||||
|
||||
for (reclen = 6; reclen <= (int)blocksize; reclen += 2)
|
||||
{
|
||||
char *tptr = buffer + blocksize - reclen;
|
||||
if (((unsigned char)tptr[0] == (unsigned char)(reclen >> 8))
|
||||
&& ((unsigned char)tptr[1] == (unsigned char)(reclen & 0xff))
|
||||
&& (tptr[2] == CALMA_STRNAME)
|
||||
&& (tptr[3] == CALMA_ASCII))
|
||||
{
|
||||
sptr = tptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sptr == NULL)
|
||||
{
|
||||
TxError("Calma output error: Structure name not found"
|
||||
" ending at GDS file position %"DLONG_PREFIX"d\n",
|
||||
(dlong)cellstart);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else if (strcmp(sptr + 4, def->cd_name))
|
||||
{
|
||||
TxError("Calma output warning: Structure definition has name"
|
||||
" %s but cell definition has name %s.\n",
|
||||
sptr + 4, def->cd_name);
|
||||
TxError("The structure definition will be given the cell name.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Calma output error: Can't read cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
freeMagic(buffer);
|
||||
}
|
||||
else if (isReadOnly)
|
||||
{
|
||||
/* Old-style GDS_BEGIN points to the start of the structure */
|
||||
/* (BGNSTR record), which is copied verbatim including the */
|
||||
/* structure name; check that the BGNSTR record is there. */
|
||||
|
||||
char header[4];
|
||||
|
||||
gzseek(fi, cellstart, SEEK_SET);
|
||||
numbytes = gzread(fi, header, sizeof(char) * 4);
|
||||
if ((numbytes != 4) || (header[2] != CALMA_BGNSTR)
|
||||
|| (header[3] != CALMA_I2))
|
||||
{
|
||||
TxError("Calma output error: Structure definition not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n",
|
||||
(dlong)cellstart);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (isReadOnly)
|
||||
{
|
||||
/* Important note: mallocMagic() is limited to size integer. */
|
||||
/* This will fail on a structure larger than ~2GB. */
|
||||
|
|
@ -1062,46 +1101,74 @@ calmaProcessDefZ(
|
|||
defsize = (size_t)(cellend - cellstart);
|
||||
buffer = (char *)mallocMagic(defsize);
|
||||
|
||||
gzseek(fi, cellstart, SEEK_SET);
|
||||
numbytes = gzread(fi, buffer, sizeof(char) * (size_t)defsize);
|
||||
|
||||
if (numbytes == defsize)
|
||||
{
|
||||
/* Sanity check: buffer must end with a structure */
|
||||
/* definition end (record 0x07). */
|
||||
|
||||
if (buffer[defsize - 4] != 0x00 ||
|
||||
buffer[defsize - 3] != 0x04 ||
|
||||
buffer[defsize - 2] != 0x07 ||
|
||||
buffer[defsize - 1] != 0x00)
|
||||
{
|
||||
TxError("Calma output error: Structure end definition not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n", cellend);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
numbytes = gzwrite(outf, buffer, sizeof(char) * (size_t)defsize);
|
||||
if (numbytes <= 0)
|
||||
{
|
||||
TxError("Calma output error: Can't write cell from "
|
||||
"vendor GDS. Using magic's internal "
|
||||
"definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (numbytes != defsize)
|
||||
{
|
||||
TxError("Calma output error: Can't read cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
|
||||
/* Additional information as to why data did not match */
|
||||
TxError("Size of data requested: %"DLONG_PREFIX"d", defsize);
|
||||
TxError("Length of data read: %"DLONG_PREFIX"d", numbytes);
|
||||
TxError("Size of data requested: %"DLONG_PREFIX"d", (dlong)defsize);
|
||||
TxError("Length of data read: %"DLONG_PREFIX"d", (dlong)numbytes);
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else if (buffer[defsize - 4] != 0x00 ||
|
||||
buffer[defsize - 3] != 0x04 ||
|
||||
buffer[defsize - 2] != 0x07 ||
|
||||
buffer[defsize - 1] != 0x00)
|
||||
{
|
||||
/* Sanity check: buffer must end with a structure */
|
||||
/* definition end (record 0x07). */
|
||||
|
||||
TxError("Calma output error: Structure end definition not found"
|
||||
" at GDS file position %"DLONG_PREFIX"d\n", cellend);
|
||||
TxError("Calma output error: Can't write cell from vendor GDS."
|
||||
" Using magic's internal definition\n");
|
||||
isReadOnly = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All sanity checks have passed, so the structure header, */
|
||||
/* name, and data can be written. Nothing may be written */
|
||||
/* to the output before this point, so that a failed check */
|
||||
/* above falls back on the cell definition in magic without */
|
||||
/* leaving a partial structure in the output. */
|
||||
|
||||
if (!oldStyle)
|
||||
{
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
||||
/* Output structure header */
|
||||
calmaOutRHZ(28, CALMA_BGNSTR, CALMA_I2, outf);
|
||||
if (CalmaDateStamp != NULL)
|
||||
calmaOutDateZ(*CalmaDateStamp, outf);
|
||||
else
|
||||
calmaOutDateZ(def->cd_timestamp, outf);
|
||||
calmaOutDateZ(time((time_t *) 0), outf);
|
||||
|
||||
/* Name structure the same as the magic cellname */
|
||||
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
numbytes = gzwrite(outf, buffer, sizeof(char) * (size_t)defsize);
|
||||
if (numbytes != defsize)
|
||||
{
|
||||
/* The structure header has already been written, so */
|
||||
/* it is not possible to fall back on the internal */
|
||||
/* cell definition; the output is corrupt and the */
|
||||
/* error is fatal. */
|
||||
|
||||
TxError("Calma output error: Failed to write cell \"%s\""
|
||||
" from vendor GDS. Output is invalid!\n",
|
||||
def->cd_name);
|
||||
freeMagic(buffer);
|
||||
gzclose(fi);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
freeMagic(buffer);
|
||||
}
|
||||
gzclose(fi);
|
||||
|
|
@ -1318,7 +1385,7 @@ calmaOutFuncZ(
|
|||
numports++;
|
||||
}
|
||||
}
|
||||
if (newll != NULL)
|
||||
if (ll != NULL)
|
||||
{
|
||||
/* Turn linked list into an array, then run qsort on it */
|
||||
/* to sort by port number. */
|
||||
|
|
|
|||
|
|
@ -131,6 +131,9 @@ typedef struct
|
|||
/* Length of record header */
|
||||
#define CALMAHEADERLENGTH 4
|
||||
|
||||
/* Largest possible record (limited by the 16-bit record length field) */
|
||||
#define CALMARECORDMAX 65535
|
||||
|
||||
/* Label types
|
||||
* The intention is all the values can be stored/converted with unsigned char type,
|
||||
* C23 allows us to be explicit with the type but C99 does not, so a comment for now.
|
||||
|
|
|
|||
Loading…
Reference in New Issue