diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/seetexk/seek.c | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff) |
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/seetexk/seek.c')
-rw-r--r-- | Build/source/texk/seetexk/seek.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/Build/source/texk/seetexk/seek.c b/Build/source/texk/seetexk/seek.c new file mode 100644 index 00000000000..67d51a60ea4 --- /dev/null +++ b/Build/source/texk/seetexk/seek.c @@ -0,0 +1,176 @@ +/* Copyright (c) 1987, 1989, 2012 University of Maryland Department of + Computer Science. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation, the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: The above copyright notice, this permission + notice and the disclaimer statement shall be included in all copies + or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/* + * SeekFile copies an input stdio file, if necessary, so that + * it produces a stdio file on which fseek() works properly. + * It returns NULL if this cannot be done; in that case, the + * input file is closed (or otherwise rendered worthless). + * + * CopyFile copies an input file unconditionally. (On non-Unix + * machines, it might `accidentally' not copy it.) + * + * On Unix machines, this means `if the input is a pipe or tty, + * copy it to a temporary file'. On other systems, all stdio files + * might happen to be seekable. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef KPATHSEA +#include <kpathsea/c-fopen.h> +#endif + +#include <stdio.h> +#include "types.h" /* for BSD_FILE_SYSTEM */ +#include "seek.h" +#include "tempfile.h" + +#include <errno.h> +#ifdef BSD_FILE_SYSTEM +#include <sys/param.h> /* want MAXBSIZE */ +#else +#include <sys/types.h> +#endif +#include <sys/stat.h> + +#ifndef KPATHSEA +long lseek(); +char *malloc(); + +extern int errno; +#endif + +/* + * Make and return a version of `f' on which fseek works (unconditionally). + * This code is somewhat Unix-specific. + */ +FILE * +CopyFile(FILE *f) +{ + register int tf, n, ifd, w; + register char *p, *buf; + register int blksize; +#ifdef BSD_FILE_SYSTEM + struct stat st; +#endif + int e; +#ifdef MAXBSIZE +#define BSIZE MAXBSIZE +#else +#define BSIZE BUFSIZ +#endif + char stackbuf[BSIZE]; +#if defined(WIN32) || defined(MSDOS) + int orig_fdmode; +#endif + const char *open_mode; + + /* get a read/write temp file which will vanish when closed */ + if ((tf = MakeRWTempFile(stackbuf)) < 0) { + e = errno; + (void) fclose(f); + errno = e; + return (NULL); + } + + /* compute buffer size and choose buffer */ + ifd = fileno(f); + buf = stackbuf; + blksize = sizeof stackbuf; +#ifdef BSD_FILE_SYSTEM + if (fstat(tf, &st) == 0 && st.st_blksize > blksize) { + /* + * The output block size is the important one, + * but the input block size is not irrelevant. + * + * This should actually compute the lcm, but we + * will rely on block sizes being powers of two + * (so that the larger is the lcm). + */ + blksize = st.st_blksize; + if (fstat(ifd, &st) == 0 && st.st_blksize > blksize) + blksize = st.st_blksize; + if ((buf = malloc((unsigned)blksize)) == NULL) { + buf = stackbuf; + blksize = sizeof stackbuf; + } + } +#endif + +#if defined(WIN32) || defined(MSDOS) + /* make sure we open the temp file in the same mode that + the original handle was open. */ + orig_fdmode = setmode(ifd, 0); + setmode(tf, orig_fdmode); +#endif + /* copy from input file to temp file */ + (void) lseek(ifd, 0L, 0); /* paranoia */ + while ((n = read(ifd, p = buf, blksize)) > 0) { + do { + if ((w = write(tf, p, n)) < 0) { + (void) close(tf); + (void) fclose(f); + return (NULL); + } + p += w; + } while ((n -= w) > 0); + } + e = errno; /* in case n < 0 */ + if (buf != stackbuf) + free(buf); + if (n < 0) { + (void) close(tf); + (void) fclose(f); + errno = e; + return (NULL); + } + + /* discard the input file, and rewind and open the temporary */ + (void) fclose(f); + (void) lseek(tf, 0L, 0); + errno = 0; +#if defined(WIN32) || defined(MSDOS) + open_mode = orig_fdmode == O_BINARY ? FOPEN_RBIN_MODE : "r"; +#else + open_mode = "r"; +#endif + if ((f = fdopen(tf, open_mode)) == NULL) { + if (errno == 0) + e = EMFILE; + (void) close(tf); + errno = e; + } + return (f); +} + +/* + * Copy an input file, but only if necessary. + */ +FILE *SeekFile(FILE *f) +{ + int fd = fileno(f); + + return (lseek(fd, 0L, 1) >= 0 && !isatty(fd) ? f : CopyFile(f)); +} |