diff --git a/calma/calmaInt.h b/calma/calmaInt.h index 9c4a7a4b..60485aa9 100644 --- a/calma/calmaInt.h +++ b/calma/calmaInt.h @@ -25,10 +25,6 @@ #include "utils/magic.h" #include "database/database.h" -#ifdef HAVE_ZLIB -#include -#endif - /* Record data types */ #define CALMA_NODATA 0 /* No data present */ #define CALMA_BITARRAY 1 /* Bit array */ @@ -140,31 +136,6 @@ typedef enum { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT, LABEL_TYPE_CEL /* ------------------------- Input macros ----------------------------- */ -#ifdef HAVE_ZLIB - #define FOPEN gzopen - #define FCLOSE gzclose - #define FGETC gzgetc - #define FREAD(a,b,c,d) gzread(d,a,b*c) - #define FEOF gzeof - #define FSEEK gzseek - #define FTELL gztell - #define REWIND gzrewind - #define FILETYPE gzFile - #define OFFTYPE z_off_t -#else - #define FOPEN fopen - #define FCLOSE fclose - #define FGETC getc - #define FREAD fread - #define FEOF feof - #define FSEEK fseek - #define FTELL ftello - #define REWIND rewind - #define FILETYPE FILE * - #define OFFTYPE off_t - #define PaZOpen PaOpen -#endif - /* Globals for Calma reading */ extern FILETYPE calmaInputFile; extern FILE *calmaInputFileNoCompression; diff --git a/commands/CmdCD.c b/commands/CmdCD.c index d1c29d63..c71355f3 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -1339,7 +1339,7 @@ CmdCellname(w, cmd) /* Make file read-write */ #ifdef FILE_LOCKS if (cellDef->cd_fd < 0) - dbReadOpen(cellDef, NULL, TRUE, NULL); + DBOpenOnly(cellDef, NULL, TRUE, NULL); if (cellDef->cd_fd == -2) { @@ -4240,9 +4240,14 @@ CmdDrc(w, cmd) break; case DRC_OFF: +#ifdef MAGIC_WRAPPER + /* Turn on long enough to force a break, then turn off */ + DRCBackGround = DRC_SET_ON; + DRCStatus = DRC_IN_PROGRESS; + DRCBreak(); +#endif DRCBackGround = DRC_SET_OFF; #ifdef MAGIC_WRAPPER - DRCBreak(); if (TxInputRedirect != TX_INPUT_REDIRECTED) #endif TxSetPrompt('%'); /* Return prompt to "normal" */ diff --git a/database/DBio.c b/database/DBio.c index ee33ad20..1d64ee80 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -99,7 +99,7 @@ static char *DBbackupFile = (char *)NULL; /* Forward declarations */ char *dbFgets(); -FILE *dbReadOpen(); +FILETYPE dbReadOpen(); int DBFileOffset; bool dbReadLabels(); bool dbReadElements(); @@ -408,7 +408,7 @@ DBAddStandardCellPaths(pathptr, level) bool dbCellReadDef(f, cellDef, name, ignoreTech, dereference) - FILE *f; /* The file, already opened by the caller */ + FILETYPE f; /* The file, already opened by the caller */ CellDef *cellDef; /* Pointer to definition of cell to be read in */ char *name; /* Name of file from which to read definition. * If NULL, then use cellDef->cd_file; if that @@ -761,7 +761,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech, dereference) * in the file beginning with 'r'. */ nextrect: - while (((c = getc(f)) == 'r') || (c == 't')) + while (((c = FGETC(f)) == 'r') || (c == 't')) { TileType dinfo; int dir; @@ -828,7 +828,7 @@ nextrect: */ if (c == '#') { - (void) fgets(line, sizeof line, f); + (void) dbFgets(line, sizeof line, f); goto nextrect; } @@ -1200,7 +1200,7 @@ DBCellRead(cellDef, name, ignoreTech, dereference, errptr) * is placed here, unless NULL. */ { - FILE *f; + FILETYPE f; bool result; if (errptr != NULL) *errptr = 0; @@ -1217,11 +1217,11 @@ DBCellRead(cellDef, name, ignoreTech, dereference, errptr) #ifdef FILE_LOCKS /* Close files that were locked by another user */ - if (cellDef->cd_fd == -2) fclose(f); + if (cellDef->cd_fd == -2) FCLOSE(f); #else /* When using fcntl() to enforce file locks, we can't */ /* close the file descriptor without losing the lock. */ - fclose(f); + FCLOSE(f); #endif } return result; @@ -1243,7 +1243,7 @@ DBCellRead(cellDef, name, ignoreTech, dereference, errptr) * to point to the name of the file from which the cell was loaded. * * Results: - * Returns an open FILE * if successful, or NULL on error. + * Returns an open FILETYPE if successful, or NULL on error. * * Side effects: * Opens a FILE. Leaves cellDef->cd_flags marked as @@ -1258,7 +1258,7 @@ DBCellRead(cellDef, name, ignoreTech, dereference, errptr) * ---------------------------------------------------------------------------- */ -FILE * +FILETYPE dbReadOpen(cellDef, name, setFileName, errptr) CellDef *cellDef; /* Def being read */ char *name; /* Name if specified, or NULL */ @@ -1268,7 +1268,8 @@ dbReadOpen(cellDef, name, setFileName, errptr) */ int *errptr; /* Pointer to int to hold error value */ { - FILE *f = NULL; + FILETYPE f = NULL; + int fd; char *filename, *realname; bool is_locked; @@ -1284,13 +1285,13 @@ dbReadOpen(cellDef, name, setFileName, errptr) if (name != (char *) NULL) { - f = PaLockOpen(name, "r", DBSuffix, Path, - CellLibPath, &filename, &is_locked); + f = PaLockZOpen(name, "r", DBSuffix, Path, + CellLibPath, &filename, &is_locked, &fd); if (errptr != NULL) *errptr = errno; } else if (cellDef->cd_file != (char *) NULL) { - /* Do not send a name with a file extension to PaLockOpen(), + /* Do not send a name with a file extension to PaLockZOpen(), * otherwise that routine must handle it and then cannot * distinguish between, say, cell.mag and cell.mag.mag. */ @@ -1308,15 +1309,15 @@ dbReadOpen(cellDef, name, setFileName, errptr) else *pptr = '\0'; - f = PaLockOpen(cellDef->cd_file, "r", DBSuffix, ".", - (char *) NULL, &filename, &is_locked); + f = PaLockZOpen(cellDef->cd_file, "r", DBSuffix, ".", + (char *) NULL, &filename, &is_locked, &fd); /* Fall back on the original method of using search paths. */ if (f == NULL) { - f = PaLockOpen(cellDef->cd_name, "r", DBSuffix, Path, - CellLibPath, &filename, &is_locked); + f = PaLockZOpen(cellDef->cd_name, "r", DBSuffix, Path, + CellLibPath, &filename, &is_locked, &fd); if (f != NULL) { @@ -1349,8 +1350,8 @@ dbReadOpen(cellDef, name, setFileName, errptr) } else { - f = PaLockOpen(cellDef->cd_name, "r", DBSuffix, Path, - CellLibPath, &filename, &is_locked); + f = PaLockZOpen(cellDef->cd_name, "r", DBSuffix, Path, + CellLibPath, &filename, &is_locked, &fd); if (errptr != NULL) *errptr = errno; } @@ -1358,7 +1359,7 @@ dbReadOpen(cellDef, name, setFileName, errptr) { /* Don't print another message if we've already tried to read it */ if (cellDef->cd_flags & CDNOTFOUND) - return ((FILE *) NULL); + return ((FILETYPE) NULL); if (name != (char *) NULL) { @@ -1381,7 +1382,7 @@ dbReadOpen(cellDef, name, setFileName, errptr) if (errptr && DBVerbose) TxError("%s\n", strerror(*errptr)); cellDef->cd_flags |= CDNOTFOUND; - return ((FILE *) NULL); + return ((FILETYPE) NULL); } #ifdef FILE_LOCKS @@ -1400,7 +1401,7 @@ dbReadOpen(cellDef, name, setFileName, errptr) if (is_locked == TRUE) cellDef->cd_fd = -2; /* Indicates locked file */ else - cellDef->cd_fd = fileno(f); + cellDef->cd_fd = fd; cellDef->cd_flags &= ~CDNOTFOUND; } #else @@ -1424,6 +1425,36 @@ dbReadOpen(cellDef, name, setFileName, errptr) return (f); } +/* + * ---------------------------------------------------------------------------- + * + * DBOpenOnly -- + * + * Form of dbReadOpen() used to check if a file is locked; it does not + * return a value. + * + * Return value: + * None. + * + * Side effects: + * See dbReadOpen() above. + * + * ---------------------------------------------------------------------------- + */ + +void +DBOpenOnly(cellDef, name, setFileName, errptr) + CellDef *cellDef; /* Def being read */ + char *name; /* Name if specified, or NULL */ + bool setFileName; /* If TRUE then cellDef->cd_file should be updated + * to point to the name of the file from which the + * cell was loaded. + */ + int *errptr; /* Pointer to int to hold error value */ +{ + dbReadOpen(cellDef, name, setFileName, errptr); +} + /* * ---------------------------------------------------------------------------- * @@ -1445,14 +1476,14 @@ DBTestOpen(name, fullPath) char *name; char **fullPath; { - FILE *f; + FILETYPE f; - f = PaLockOpen(name, "r", DBSuffix, Path, CellLibPath, - fullPath, (bool *)NULL); + f = PaLockZOpen(name, "r", DBSuffix, Path, CellLibPath, + fullPath, (bool *)NULL, (int *)NULL); if (f != NULL) { - fclose(f); + FCLOSE(f); return TRUE; } return FALSE; @@ -1485,7 +1516,7 @@ dbReadUse(cellDef, line, len, f, scalen, scaled, dereference, dbUseTable) CellDef *cellDef; /* Cell whose cells are being read */ char *line; /* Line containing "use ..." */ int len; /* Size of buffer pointed to by line */ - FILE *f; /* Input file */ + FILETYPE f; /* Input file */ int scalen; /* Multiply values in file by this */ int scaled; /* Divide values in file by this */ bool dereference; /* If TRUE, ignore path references */ @@ -1796,7 +1827,7 @@ badTransform: if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr) && (dereference == FALSE) && (firstUse == TRUE)) { - FILE *ftest; + FILETYPE ftest; TxError("Duplicate cell in %s: Instance of cell %s is from " "path %s but cell was previously read from %s.\n", @@ -1806,7 +1837,7 @@ badTransform: /* Test file at path. If path is invalid then ignore it */ /* (automatic dereferencing due to unavailability). */ - ftest = PaOpen(cellname, "r", DBSuffix, pathptr, (char *)NULL, + ftest = PaZOpen(cellname, "r", DBSuffix, pathptr, (char *)NULL, (char **) NULL); if (ftest == NULL) { @@ -1818,7 +1849,7 @@ badTransform: int i = 0; /* To do: Run checksum on file (not yet implemented) */ - fclose(ftest); + FCLOSE(ftest); while (TRUE) { @@ -1873,7 +1904,7 @@ badTransform: if ((pathOK == FALSE) && strcmp(cwddir, pathptr) && (dereference == FALSE) && (firstUse == TRUE)) { - FILE *ftest; + FILETYPE ftest; TxError("Duplicate cell in %s: Instance of cell %s is from " "path %s but cell was previously read from " @@ -1883,7 +1914,7 @@ badTransform: /* Test file at path. If path is invalid then ignore */ /* it (automatic dereferencing due to unavailability). */ - ftest = PaOpen(cellname, "r", DBSuffix, pathptr, (char *)NULL, + ftest = PaZOpen(cellname, "r", DBSuffix, pathptr, (char *)NULL, (char **) NULL); if (ftest == NULL) { @@ -1895,7 +1926,7 @@ badTransform: int i = 0; /* To do: Run checksum on file (not yet implemented) */ - fclose(ftest); + FCLOSE(ftest); while (TRUE) { @@ -2009,7 +2040,7 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled) CellDef *cellDef; /* Cell whose elements are being read */ char *line; /* Line containing << elements >> */ int len; /* Size of buffer pointed to by line */ - FILE *f; /* Input file */ + FILETYPE f; /* Input file */ int scalen; /* Scale up by this factor */ int scaled; /* Scale down by this factor */ { @@ -2139,7 +2170,7 @@ dbReadElements(cellDef, line, len, f, scalen, scaled) CellDef *cellDef; /* Cell whose elements are being read */ char *line; /* Line containing << elements >> */ int len; /* Size of buffer pointed to by line */ - FILE *f; /* Input file */ + FILETYPE f; /* Input file */ int scalen; /* Scale up by this factor */ int scaled; /* Scale down by this factor */ { @@ -2313,7 +2344,7 @@ dbReadLabels(cellDef, line, len, f, scalen, scaled) CellDef *cellDef; /* Cell whose labels are being read */ char *line; /* Line containing << labels >> */ int len; /* Size of buffer pointed to by line */ - FILE *f; /* Input file */ + FILETYPE f; /* Input file */ int scalen; /* Scale up by this factor */ int scaled; /* Scale down by this factor */ { @@ -2631,7 +2662,7 @@ char * dbFgets(line, len, f) char *line; int len; - FILE *f; + FILETYPE f; { char *cs; int l; @@ -2640,7 +2671,7 @@ dbFgets(line, len, f) do { cs = line, l = len; - while (--l > 0 && (c = getc(f)) != EOF) + while (--l > 0 && (c = FGETC(f)) != EOF) { if (c != '\r') *cs++ = c; if (c == '\n') @@ -3633,9 +3664,11 @@ DBCellWrite(cellDef, fileName) { struct stat thestat; bool is_locked; + int fd; + #ifdef FILE_LOCKS if (FileLocking) - realf = flock_open(expandname, "r", &is_locked); + realf = flock_open(expandname, "r", &is_locked, NULL); else #endif realf = fopen(expandname, "r"); @@ -3647,7 +3680,7 @@ DBCellWrite(cellDef, fileName) } else { - int fd = fileno(realf); + fd = fileno(realf); fstat(fd, &thestat); if (thestat.st_size != DBFileOffset) { @@ -4024,11 +4057,11 @@ DBGetTech(cellName) * is desired. */ { - FILE *f; + FILETYPE f; static char line[512]; char *p; - f = PaOpen(cellName, "r", DBSuffix, Path, CellLibPath, (char **) NULL); + f = PaZOpen(cellName, "r", DBSuffix, Path, CellLibPath, (char **) NULL); if (f == NULL) return NULL; p = (char *) NULL; @@ -4043,7 +4076,7 @@ DBGetTech(cellName) /* Find the tech name */; ret: - (void) fclose(f); + (void) FCLOSE(f); f = NULL; return (p); } diff --git a/database/database.h.in b/database/database.h.in index cbfe118c..1e677fed 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -951,7 +951,7 @@ extern TileType DBTransformDiagonal(); extern void DBEraseValid(); extern void DBPaintValid(); extern void DBTreeCountPaint(); -extern FILE *dbReadOpen(); +extern void DBOpenOnly(); extern int DBLoadFont(); extern int DBNameToFont(); extern int DBFontChar(); diff --git a/dbwind/DBWprocs.c b/dbwind/DBWprocs.c index 2d982777..675a967c 100644 --- a/dbwind/DBWprocs.c +++ b/dbwind/DBWprocs.c @@ -360,6 +360,13 @@ DBWloadWindow(window, name, flags) else rootname++; + /* Strip off any ".gz" extension from the name */ + dotptr = strrchr(rootname, '.'); + + if (dotptr != NULL) + if (!strcmp(dotptr, ".gz")) + *dotptr = '\0'; + /* Strip off any ".mag" extension from the name */ dotptr = strrchr(rootname, '.'); diff --git a/drc/DRCcontin.c b/drc/DRCcontin.c index f1e18d95..b24ff556 100644 --- a/drc/DRCcontin.c +++ b/drc/DRCcontin.c @@ -533,6 +533,7 @@ DRCContinuous() } } UndoDisable(); + /* fprintf(stderr, "DRC continuing internally. . .\n"); fflush(stderr); */ #else #ifndef USE_IO_PROBE diff --git a/tcltk/tclmagic.c b/tcltk/tclmagic.c index 4d5405da..5ef9200b 100644 --- a/tcltk/tclmagic.c +++ b/tcltk/tclmagic.c @@ -369,8 +369,8 @@ _tcl_dispatch(ClientData clientData, /* with the same name that returns an error. However, this */ /* rule hangs magic when the "load" command is used on a shared */ /* object file that fails to load properly. So if the filename */ - /* has an extension which is not ".mag", we will return the */ - /* error. */ + /* has an extension which is not ".mag" or ".gz", we will */ + /* return the error. */ /* Updated 1/20/2015: Need to check for a '.' AFTER the last */ /* slash, so as to avoid problems with ./, ../, etc. */ @@ -387,7 +387,7 @@ _tcl_dispatch(ClientData clientData, slashptr++; if ((dotptr = strrchr(slashptr, '.')) != NULL) - if (strcmp(dotptr + 1, "mag")) + if (strcmp(dotptr + 1, "mag") && strcmp(dotptr + 1, "gz")) return result; } } diff --git a/utils/LIBdbio.c b/utils/LIBdbio.c index 36e619b3..0a1e03e9 100644 --- a/utils/LIBdbio.c +++ b/utils/LIBdbio.c @@ -45,14 +45,16 @@ static char rcsid[] = "$Header: /usr/cvsroot/magic-8.0/utils/LIBdbio.c,v 1.1.1.1 */ FILE * -flock_open(filename, mode, is_locked) +flock_open(filename, mode, is_locked, fdb) char *filename; char *mode; bool *is_locked; + int *fdb; { FILE *f; if (is_locked) *is_locked = FALSE; f = fopen(filename, mode); + if ((f >= 0) && (fdb != NULL)) *fdb = fileno(f); return(f); } diff --git a/utils/flock.c b/utils/flock.c index 5e01a259..5117bc99 100644 --- a/utils/flock.c +++ b/utils/flock.c @@ -80,6 +80,128 @@ #include #include +#ifdef HAVE_ZLIB + +#include + +/* + *------------------------------------------------------------------------- + * flock_zopen -- + * + * Open a compressed file with "lockf" file locking method. + * + * Results -- + * Pointer to FILE that was opened, or NULL if an error occurred. + * + * Side effects -- + * System I/O + *------------------------------------------------------------------------- + */ + +gzFile flock_zopen(filename, mode, is_locked, fdp) + char *filename; + char *mode; + bool *is_locked; + int *fdp; +{ + int fd; + gzFile f = NULL; + struct flock fl; + char *fname; + + if (is_locked) *is_locked = FALSE; + + /* Check if file is compressed (has a .gz extension) */ + + fname = PaCheckCompressed(filename); + + /* If is_locked is NULL, then a lock is not requested, so just do */ + /* a normal gzopen() and return. */ + + if (is_locked == NULL) + { + int oflag = 0; + + if (mode[0] == 'r') + oflag = (mode[1] == '+') ? O_RDWR : O_RDONLY; + else if (mode[0] == 'w') + oflag = (mode[1] == '+') ? O_APPEND : O_WRONLY; + + fd = open(fname, oflag); + if (fdp != NULL) *fdp = fd; + if (fname != filename) freeMagic(fname); + return gzdopen(fd, mode); + } + + /* Diagnostic */ + /* TxPrintf("Opening file <%s>\n", fname); */ + + fd = open(fname, O_RDWR); + if (fd < 0) + { + if (is_locked) *is_locked = TRUE; + fd = open(fname, O_RDONLY); + f = gzdopen(fd, "r"); + goto done; + } + + fl.l_len = 0; + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_type = F_WRLCK; + fl.l_pid = getpid(); + + if (fcntl(fd, F_GETLK, &fl)) + { + perror(fname); + f = gzdopen(fd, mode); + goto done; + } + close(fd); + fd = -1; + + if (fl.l_type == F_UNLCK) + { + fl.l_len = 0; + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_type = F_WRLCK; + fl.l_pid = getpid(); + + fd = open(fname, O_RDWR); + if (fcntl(fd, F_SETLK, &fl)) + { + perror(fname); + } + else + { + /* Diagnostic */ + /* TxPrintf("Obtained lock on file <%s> (fd=%d)\n", fname, fd); */ + } + f = gzdopen(fd, mode); + } + else + { + /* Don't know why PID is not set by F_GETLK as advertised? */ + if (fl.l_pid == 0) + TxPrintf("File <%s> is already locked by another process." + " Opening read-only.\n", fname); + else + TxPrintf("File <%s> is already locked by pid %d. Opening read-only.\n", + fname, (int)fl.l_pid); + if (is_locked) *is_locked = TRUE; + fd = open(fname, O_RDONLY); + f = gzdopen(fd, "r"); + } + +done: + if (fdp != NULL) *fdp = fd; + if (fname != filename) freeMagic(fname); + return f; +} + +#endif /* HAVE_ZLIB */ + /* *------------------------------------------------------------------------- * flock_open -- @@ -90,24 +212,32 @@ * Pointer to FILE that was opened, or NULL if an error occurred. * * Side effects -- + * fdp pointer value filled with the file descriptor. * System I/O *------------------------------------------------------------------------- */ -FILE *flock_open(filename, mode, is_locked) +FILE *flock_open(filename, mode, is_locked, fdp) char *filename; char *mode; bool *is_locked; + int *fdp; { FILE *f = NULL, *tmp; struct flock fl; + if (fdp != NULL) *fdp = -1; if (is_locked) *is_locked = FALSE; /* If is_locked is NULL, then a lock is not requested, so just do */ /* a normal fopen() and return. */ - if (is_locked == NULL) return fopen(filename, mode); + if (is_locked == NULL) + { + f = fopen(filename, mode); + if ((fdp != NULL) && (f != NULL)) *fdp = fileno(f); + return f; + } /* Diagnostic */ /* TxPrintf("Opening file <%s>\n", filename); */ @@ -167,6 +297,7 @@ FILE *flock_open(filename, mode, is_locked) } done: + if ((fdp != NULL) && (f != NULL)) *fdp = fileno(f); return f; } diff --git a/utils/getrect.c b/utils/getrect.c index 0e4d7800..f5a572a0 100644 --- a/utils/getrect.c +++ b/utils/getrect.c @@ -55,7 +55,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ int GetRect(fin, skip, rect, scalen, scaled) - FILE *fin; + FILETYPE fin; int skip; /* Number of bytes to skip before rect */ Rect *rect; /* Pointer to rectangle to be filled in */ int scalen; /* Scale up by this amount */ @@ -67,31 +67,31 @@ GetRect(fin, skip, rect, scalen, scaled) int dir = 0x1; while (skip-- > 0) - (void) getc(fin); + (void) FGETC(fin); - if (isNegative = ((c = getc(fin)) == '-')) c = getc(fin); - for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + if (isNegative = ((c = FGETC(fin)) == '-')) c = FGETC(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = FGETC(fin)) /* Nothing */; rect->r_xbot = isNegative ? -n : n; if (!isspace(c)) goto bad; - while ((c = getc(fin)) != EOF && isspace(c)) /* Nothing */; + while ((c = FGETC(fin)) != EOF && isspace(c)) /* Nothing */; - if (isNegative = (c == '-')) c = getc(fin); - for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + if (isNegative = (c == '-')) c = FGETC(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = FGETC(fin)) /* Nothing */; rect->r_ybot = isNegative ? -n : n; if (!isspace(c)) goto bad; - while ((c = getc(fin)) != EOF && isspace(c)) /* Nothing */; + while ((c = FGETC(fin)) != EOF && isspace(c)) /* Nothing */; - if (isNegative = (c == '-')) c = getc(fin); - for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + if (isNegative = (c == '-')) c = FGETC(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = FGETC(fin)) /* Nothing */; rect->r_xtop = isNegative ? -n : n; if (!isspace(c)) goto bad; - while ((c = getc(fin)) != EOF && isspace(c)) /* Nothing */; + while ((c = FGETC(fin)) != EOF && isspace(c)) /* Nothing */; - if (isNegative = (c == '-')) c = getc(fin); - for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + if (isNegative = (c == '-')) c = FGETC(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = FGETC(fin)) /* Nothing */; rect->r_ytop = isNegative ? -n : n; @@ -112,7 +112,7 @@ GetRect(fin, skip, rect, scalen, scaled) while (c != EOF && c != '\n') { - c = getc(fin); + c = FGETC(fin); switch ((char)c) { case 's': @@ -127,6 +127,6 @@ GetRect(fin, skip, rect, scalen, scaled) bad: while (c != EOF && c != '\n') - c = getc(fin); + c = FGETC(fin); return (FALSE); } diff --git a/utils/magic.h b/utils/magic.h index f118956b..d0b78e67 100644 --- a/utils/magic.h +++ b/utils/magic.h @@ -25,6 +25,10 @@ #include #include +#ifdef HAVE_ZLIB +#include +#endif + /* ------------------- Universal pointer typecast --------------------- */ /* Set default value for backwards compatibility with non-autoconf make */ @@ -130,6 +134,34 @@ extern char *MagicRevision; extern char *MagicCompileTime; extern char AbortMessage[]; +/* ------------ zlib (compression) support -------------------------------- */ + +#ifdef HAVE_ZLIB + #define FOPEN gzopen + #define FCLOSE gzclose + #define FGETC gzgetc + #define FREAD(a,b,c,d) gzread(d,a,b*c) + #define FEOF gzeof + #define FSEEK gzseek + #define FTELL gztell + #define REWIND gzrewind + #define FILETYPE gzFile + #define OFFTYPE z_off_t +#else + #define FOPEN fopen + #define FCLOSE fclose + #define FGETC getc + #define FREAD fread + #define FEOF feof + #define FSEEK fseek + #define FTELL ftello + #define REWIND rewind + #define FILETYPE FILE * + #define OFFTYPE off_t + #define PaZOpen PaOpen + #define PaLockZOpen PaLockOpen +#endif + /* ---------------- Start of Machine Configuration Section ----------------- */ /* ------- Configuration: Handle Missing Routines/Definitions ------- */ diff --git a/utils/path.c b/utils/path.c index e8fb194c..852b2ef2 100644 --- a/utils/path.c +++ b/utils/path.c @@ -27,6 +27,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include #include #include +#include +#include #ifdef HAVE_ZLIB #include @@ -58,6 +60,47 @@ bool FileLocking = TRUE; #define MAXSIZE MAXPATHLEN +#ifdef HAVE_ZLIB +/* + *------------------------------------------------------------------- + * + * PaCheckCompressed() --- + * + * Check if a file is compressed by adding ".gz" to the name and + * attempting to open the file. + * + * Return value: + * The string value that resulted in a valid file descriptor. + * This is a dynamically allocated string *or* a pointer to the + * original filename; the calling routine should check and + * free if needed. + * + *------------------------------------------------------------------- + */ + +char * +PaCheckCompressed(filename) + char *filename; +{ + int fd; + char *gzname; + + gzname = (char *)mallocMagic(strlen(filename) + 4); + sprintf(gzname, "%s.gz", filename); + + fd = open(gzname, O_RDONLY); + if (fd < 0) + { + freeMagic(gzname); + gzname = filename; + } + else + close(fd); + + return gzname; +} +#endif /* HAVE_ZLIB */ + /*------------------------------------------------------------------- * PaAppend -- * Add a string to the designated path variable. @@ -357,6 +400,204 @@ nextName(ppath, file, dest, size) return dest; } +#ifdef HAVE_ZLIB + +/*------------------------------------------------------------------- + * PaLockZOpen -- + * This routine does a file lookup using the current path and + * supplying a default extension. + * + * Results: + * A gzFile type, or NULL if the file couldn't be found. + * + * Side Effects: + *------------------------------------------------------------------- + */ + +gzFile +PaLockZOpen(file, mode, ext, path, library, pRealName, is_locked, fdp) + char *file; /* Name of the file to be opened. */ + char *mode; /* The file mode, as given to fopen. */ + char *ext; /* The extension to be added to the file name, + * or NULL. Note: this string must include + * the dot (or whatever separator you use). + */ + char *path; /* A search path: a list of directory names + * separated by colons or blanks. To use + * only the working directory, use "." for + * the path. + */ + char *library; /* A 2nd path containing library names. Can be + * NULL to indicate no library. + */ + char **pRealName; /* Pointer to a location that will be filled + * in with the address of the real name of + * the file that was successfully opened. + * If NULL, then nothing is stored. + */ + bool *is_locked; /* Pointer to a location to store the result + * of the attempt to grab an advisory lock + * on the file. If NULL, then nothing is + * stored. + */ + int *fdp; /* If non-NULL, put the file descriptor here */ +{ + char extendedName[MAXSIZE], *p1, *p2; + static char realName[MAXSIZE]; + int length, extLength, i, fd; + int oflag = 0; + gzFile f; + + if (fdp != NULL) *fdp = -1; + if (file == NULL) return (gzFile) NULL; + if (file[0] == '\0') return (gzFile) NULL; + if (pRealName != NULL) (*pRealName) = realName; + + /* Get equivalent flag for file descriptor mode */ + if (mode[0] == 'r') + oflag = (mode[1] == '+') ? O_RDWR : O_RDONLY; + else if (mode[0] == 'w') + oflag = (mode[1] == '+') ? O_APPEND : O_WRONLY; + + /* See if we must supply an extension. */ + + length = strlen(file); + if (length >= MAXSIZE) length = MAXSIZE - 1; + if (ext != NULL) + { + (void) strncpy(extendedName, file, length + 1); + i = MAXSIZE - 1 - length; + extLength = strlen(ext); + if (extLength > i) extLength = i; + + /* (Modified by Tim, 1/13/2015; assume that "file" has */ + /* the extension already stripped, therefore always add */ + /* the extension if one is specified. This allows the */ + /* code to distinguish between, say, "a.mag" and */ + /* "a.mag.mag".) */ + + /* If the extension is already on the name, don't add it */ + // if ((length < extLength) || ((extLength > 0) + // && (strcmp(ext, file + length - extLength)))) + + (void) strncpy(&(extendedName[length]), ext, extLength + 1); + + extendedName[MAXSIZE-1] = '\0'; + file = extendedName; + } + + /* If the first character of the file name is a tilde or dollar sign, + * do tilde or environment variable expansion but don't touch a search + * path. + */ + + if (file[0] == '~' || file[0] == '$') + { + p1 = realName; + p2 = file; + if (PaExpand(&p2, &p1, MAXSIZE) < 0) return NULL; + +#ifdef FILE_LOCKS + if (FileLocking) + return flock_zopen(realName, mode, is_locked, fdp); + else +#endif + fd = open(realName, oflag); + + if (fdp != NULL) *fdp = fd; + return gzdopen(fd, mode); + } + + /* If we were already given a full rooted file name, + * or a relative pathname, just use it. + */ + + if (file[0] == '/' + || (file[0] == '.' && (strcmp(file, ".") == 0 + || strncmp(file, "./", 2) == 0 + || strcmp(file, "..") == 0 + || strncmp(file, "../", 3) == 0))) + { + (void) strncpy(realName, file, MAXSIZE-1); + realName[MAXSIZE-1] = '\0'; + +#ifdef FILE_LOCKS + if (FileLocking) + return flock_zopen(realName, mode, is_locked, fdp); + else +#endif + fd = open(realName, oflag); + + if (fdp != NULL) *fdp = fd; + return gzdopen(fd, mode); + } + + /* Now try going through the path, one entry at a time. */ + + while (nextName(&path, file, realName, MAXSIZE) != NULL) + { + if (*realName == 0) continue; + +#ifdef FILE_LOCKS + if (FileLocking) + f = flock_zopen(realName, mode, is_locked, &fd); + else + { + fd = open(realName, oflag); + f = gzdopen(fd, mode); + } +#else + fd = open(realName, oflag); + f = gzdopen(fd, mode); +#endif + + if (f != NULL) + { + if (fdp != NULL) *fdp = fd; + return f; + } + + // If any error other than "file not found" occurred, + // then halt immediately. + if (errno != ENOENT) return NULL; + } + + /* We've tried the path and that didn't work. Now go through + * the library area, one entry at a time. + */ + + if (library == NULL) return NULL; + while (nextName(&library, file, realName, MAXSIZE) != NULL) + { +#ifdef FILE_LOCKS + if (FileLocking) + f = flock_zopen(realName, mode, is_locked, &fd); + else + { + fd = open(realName, oflag); + f = gzdopen(fd, mode); + } +#else + fd = open(realName, oflag); + f = gzdopen(fd, mode); +#endif + + if (f != NULL) + { + if (fdp != NULL) *fdp = fd; + return f; + } + + // If any error other than "file not found" occurred, + // then halt immediately. + if (errno != ENOENT) return NULL; + } + + return NULL; +} + +#endif /* HAVE_ZLIB */ + /*------------------------------------------------------------------- * PaLockOpen -- * This routine does a file lookup using the current path and @@ -389,7 +630,7 @@ nextName(ppath, file, dest, size) */ FILE * -PaLockOpen(file, mode, ext, path, library, pRealName, is_locked) +PaLockOpen(file, mode, ext, path, library, pRealName, is_locked, fdp) char *file; /* Name of the file to be opened. */ char *mode; /* The file mode, as given to fopen. */ char *ext; /* The extension to be added to the file name, @@ -414,12 +655,14 @@ PaLockOpen(file, mode, ext, path, library, pRealName, is_locked) * on the file. If NULL, then nothing is * stored. */ + int *fdp; /* If non-NULL, put the file descriptor here. */ { char extendedName[MAXSIZE], *p1, *p2; static char realName[MAXSIZE]; int length, extLength, i; FILE *f; + if (fdp != NULL) *fdp = -1; if (file == NULL) return (FILE *) NULL; if (file[0] == '\0') return (FILE *) NULL; if (pRealName != NULL) (*pRealName) = realName; @@ -464,10 +707,13 @@ PaLockOpen(file, mode, ext, path, library, pRealName, is_locked) #ifdef FILE_LOCKS if (FileLocking) - return flock_open(realName, mode, is_locked); + f = flock_open(realName, mode, is_locked, NULL); else #endif - return fopen(realName, mode); + f = fopen(realName, mode); + + if ((fdp != NULL) && (f != NULL)) *fdp = fileno(f); + return f; } /* If we were already given a full rooted file name, @@ -485,10 +731,13 @@ PaLockOpen(file, mode, ext, path, library, pRealName, is_locked) #ifdef FILE_LOCKS if (FileLocking) - return flock_open(realName, mode, is_locked); + f = flock_open(realName, mode, is_locked, NULL); else #endif - return fopen(realName, mode); + f = fopen(realName, mode); + + if ((fdp != NULL) && (f != NULL)) *fdp = fileno(f); + return f; } /* Now try going through the path, one entry at a time. */ @@ -499,12 +748,16 @@ PaLockOpen(file, mode, ext, path, library, pRealName, is_locked) #ifdef FILE_LOCKS if (FileLocking) - f = flock_open(realName, mode, is_locked); + f = flock_open(realName, mode, is_locked, NULL); else #endif f = fopen(realName, mode); - if (f != NULL) return f; + if (f != NULL) + { + if (fdp != NULL) *fdp = fileno(f); + return f; + } // If any error other than "file not found" occurred, // then halt immediately. @@ -520,12 +773,16 @@ PaLockOpen(file, mode, ext, path, library, pRealName, is_locked) { #ifdef FILE_LOCKS if (FileLocking) - f = flock_open(realName, mode, is_locked); + f = flock_open(realName, mode, is_locked, NULL); else #endif f = fopen(realName, mode); - if (f != NULL) return f; + if (f != NULL) + { + if (fdp != NULL) *fdp = fileno(f); + return f; + } // If any error other than "file not found" occurred, // then halt immediately. @@ -705,7 +962,7 @@ PaOpen(file, mode, ext, path, library, pRealName) * If NULL, then nothing is stored. */ { - return PaLockOpen(file, mode, ext, path, library, pRealName, NULL); + return PaLockOpen(file, mode, ext, path, library, pRealName, NULL, NULL); } /* diff --git a/utils/runstats.c b/utils/runstats.c index f681fc52..35e34b98 100644 --- a/utils/runstats.c +++ b/utils/runstats.c @@ -26,21 +26,19 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include #include #include +#include #include "utils/magic.h" #include "utils/runstats.h" /* Library imports: */ -#ifndef __APPLE__ +#ifdef CYGWIN extern char *sbrk(); extern int end; #else -#ifndef CYGWIN -extern void *sbrk(); int end; #endif -#endif /* * ---------------------------------------------------------------------------- diff --git a/utils/utils.h b/utils/utils.h index 0a3aa4fd..8aa92967 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -49,7 +49,7 @@ extern int LookupStructFull(); extern int PaExpand(char **, char **, int); extern char *nextName(); extern FILE *PaOpen(char *, char *, char *, char *, char *, char **); -extern FILE *PaLockOpen(char *, char *, char *, char *, char *, char **, bool *); +extern FILE *PaLockOpen(char *, char *, char *, char *, char *, char **, bool *, int *); extern char *StrDup(char **, char *); extern int Match(); extern char *ArgStr(); @@ -79,12 +79,17 @@ extern bool ParsSplit(); #ifdef HAVE_ZLIB extern gzFile PaZOpen(char *, char *, char *, char *, char *, char **); +extern gzFile PaLockZOpen(char *, char *, char *, char *, char *, char **, bool *, int *); +extern char *PaCheckCompressed(char *); #endif extern int SetNoisyBool(bool *, char *, FILE *); #ifdef FILE_LOCKS extern FILE *flock_open(); +#ifdef HAVE_ZLIB +extern gzFile flock_zopen(); +#endif #endif /* The following macro takes an integer and returns another integer that