+2008-02-29 Bruno Haible <bruno@clisp.org>
+
+ New module 'freadseek'.
+ * modules/freadseek: New file.
+ * lib/freadseek.h: New file.
+ * lib/freadseek.c: New file.
+ * MODULES.html.sh (File stream based Input/Output): Add freadseek.
+
2008-02-29 Sergey Poznyakoff <gray@gnu.org.ua>
* users.txt: Add anubis, cpio, mailfromd, mailutils, radius,
--- /dev/null
+/* Skipping input from a FILE stream.
+ Copyright (C) 2007-2008 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "freadseek.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "freadahead.h"
+
+int
+freadseek (FILE *fp, size_t offset)
+{
+ size_t buffered;
+ int fd;
+
+ if (offset == 0)
+ return 0;
+
+ /* Increment the in-memory pointer. This is very cheap (no system calls). */
+ buffered = freadahead (fp);
+ if (buffered > 0)
+ {
+ size_t increment = (buffered < offset ? buffered : offset);
+
+ /* Keep this code in sync with freadahead and freadptr! */
+#if defined _IO_ferror_unlocked /* GNU libc, BeOS */
+ fp->_IO_read_ptr += increment;
+#elif defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
+ fp->_p += increment;
+ fp->_r -= increment;
+#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
+# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
+# define fp_ ((struct { unsigned char *_ptr; \
+ unsigned char *_base; \
+ unsigned char *_end; \
+ long _cnt; \
+ int _file; \
+ unsigned int _flag; \
+ } *) fp)
+ fp_->_ptr += increment;
+ fp_->_cnt -= increment;
+# else
+ fp->_ptr += increment;
+ fp->_cnt -= increment;
+# endif
+#elif defined __UCLIBC__ /* uClibc */
+# ifdef __STDIO_BUFFERS
+ fp->__bufpos += increment;
+# else
+ abort ();
+# endif
+#elif defined __QNX__ /* QNX */
+ fp->_Next += increment;
+#else
+ #error "Please port gnulib freadseek.c to your platform! Look at the definition of getc, getc_unlocked on your system, then report this to bug-gnulib."
+#endif
+
+ offset -= increment;
+ if (offset == 0)
+ return 0;
+ }
+
+ /* Test whether the stream is seekable or not. */
+ fd = fileno (fp);
+ if (fd >= 0 && lseek (fd, 0, SEEK_CUR) >= 0)
+ {
+ /* FP refers to a regular file. fseek is most efficient in this case. */
+ return fseek (fp, offset, SEEK_CUR);
+ }
+ else
+ {
+ /* FP is a non-seekable stream, possibly not even referring to a file
+ descriptor. Read OFFSET bytes explicitly and discard them. */
+ char buf[4096];
+
+ do
+ {
+ size_t count = (sizeof (buf) < offset ? sizeof (buf) : offset);
+ if (fread (buf, 1, count, fp) < count)
+ {
+ if (ferror (fp))
+ /* EOF, or error before or while reading. */
+ return EOF;
+ else
+ /* Encountered EOF. */
+ return 0;
+ }
+ offset -= count;
+ }
+ while (offset > 0);
+
+ return 0;
+ }
+}
--- /dev/null
+/* Skipping input from a FILE stream.
+ Copyright (C) 2007-2008 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Assuming the stream STREAM is open for reading:
+
+ Read and discard OFFSET bytes from STREAM.
+
+ freadseek (STREAM, OFFSET) is the same as
+ fseek (STREAM, OFFSET, SEEK_CUR), except that the latter does not work
+ on non-seekable input streams (such as pipes).
+
+ Upon success, return 0.
+ Upon premature end of stream, return 0 (like fseek does).
+ Upon error, set the error indicator in the stream and return EOF.
+
+ STREAM must not be wide-character oriented. */
+
+extern int freadseek (FILE *stream, size_t offset);
+
+#ifdef __cplusplus
+}
+#endif