| # ftello.m4 | |
| # serial 17 | |
| dnl Copyright (C) 2007-2026 Free Software Foundation, Inc. | |
| dnl This file is free software; the Free Software Foundation | |
| dnl gives unlimited permission to copy and/or distribute it, | |
| dnl with or without modifications, as long as this notice is preserved. | |
| dnl This file is offered as-is, without any warranty. | |
| AC_DEFUN([gl_FUNC_FTELLO], | |
| [ | |
| AC_REQUIRE([gl_STDIO_H_DEFAULTS]) | |
| AC_REQUIRE([AC_PROG_CC]) | |
| AC_REQUIRE([gl_STDIN_LARGE_OFFSET]) | |
| AC_REQUIRE([gl_SYS_TYPES_H]) | |
| dnl Persuade glibc <stdio.h> to declare ftello(). | |
| AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) | |
| AC_CHECK_DECLS_ONCE([ftello]) | |
| if test $ac_cv_have_decl_ftello = no; then | |
| HAVE_DECL_FTELLO=0 | |
| fi | |
| AC_CACHE_CHECK([for ftello], [gl_cv_func_ftello], | |
| [ | |
| AC_LINK_IFELSE( | |
| [AC_LANG_PROGRAM( | |
| [[#include <stdio.h>]], | |
| [[ftello (stdin);]])], | |
| [gl_cv_func_ftello=yes], | |
| [gl_cv_func_ftello=no]) | |
| ]) | |
| if test $gl_cv_func_ftello = no; then | |
| HAVE_FTELLO=0 | |
| else | |
| if test $WINDOWS_64_BIT_OFF_T = 1; then | |
| REPLACE_FTELLO=1 | |
| fi | |
| if test $gl_cv_var_stdin_large_offset = no; then | |
| REPLACE_FTELLO=1 | |
| fi | |
| AC_REQUIRE([AC_CANONICAL_HOST]) | |
| if test $REPLACE_FTELLO = 0; then | |
| dnl On native Windows, in some circumstances, ftell(), ftello(), | |
| dnl fgetpos(), lseek(), _lseeki64() all succeed on devices of type | |
| dnl FILE_TYPE_PIPE. However, to match POSIX behaviour, we want | |
| dnl ftell(), ftello(), fgetpos(), lseek() to fail when the argument fd | |
| dnl designates a pipe. See also | |
| dnl https://github.com/python/cpython/issues/78961#issuecomment-1093800325 | |
| case "$host_os" in | |
| mingw* | windows*) REPLACE_FTELLO=1 ;; | |
| esac | |
| fi | |
| if test $REPLACE_FTELLO = 0; then | |
| dnl Detect bug on Solaris. | |
| dnl ftell and ftello produce incorrect results after putc that followed a | |
| dnl getc call that reached EOF on Solaris. This is because the _IOREAD | |
| dnl flag does not get cleared in this case, even though _IOWRT gets set, | |
| dnl and ftell and ftello look whether the _IOREAD flag is set. | |
| AC_CACHE_CHECK([whether ftello works], | |
| [gl_cv_func_ftello_works], | |
| [ | |
| dnl Initial guess, used when cross-compiling or when /dev/tty cannot | |
| dnl be opened. | |
| changequote(,)dnl | |
| case "$host_os" in | |
| # Guess no on Solaris. | |
| solaris*) gl_cv_func_ftello_works="guessing no" ;; | |
| # Guess yes on native Windows. | |
| mingw* | windows*) gl_cv_func_ftello_works="guessing yes" ;; | |
| # Guess yes otherwise. | |
| *) gl_cv_func_ftello_works="guessing yes" ;; | |
| esac | |
| changequote([,])dnl | |
| AC_RUN_IFELSE( | |
| [AC_LANG_SOURCE([[ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #define TESTFILE "conftest.tmp" | |
| int | |
| main (void) | |
| { | |
| FILE *fp; | |
| /* Create a file with some contents. */ | |
| fp = fopen (TESTFILE, "w"); | |
| if (fp == NULL) | |
| return 70; | |
| if (fwrite ("foogarsh", 1, 8, fp) < 8) | |
| { fclose (fp); return 71; } | |
| if (fclose (fp)) | |
| return 72; | |
| /* The file's contents is now "foogarsh". */ | |
| /* Try writing after reading to EOF. */ | |
| fp = fopen (TESTFILE, "r+"); | |
| if (fp == NULL) | |
| return 73; | |
| if (fseek (fp, -1, SEEK_END)) | |
| { fclose (fp); return 74; } | |
| if (!(getc (fp) == 'h')) | |
| { fclose (fp); return 1; } | |
| if (!(getc (fp) == EOF)) | |
| { fclose (fp); return 2; } | |
| if (!(ftell (fp) == 8)) | |
| { fclose (fp); return 3; } | |
| if (!(ftell (fp) == 8)) | |
| { fclose (fp); return 4; } | |
| if (!(putc ('!', fp) == '!')) | |
| { fclose (fp); return 5; } | |
| if (!(ftell (fp) == 9)) | |
| { fclose (fp); return 6; } | |
| if (!(fclose (fp) == 0)) | |
| return 7; | |
| fp = fopen (TESTFILE, "r"); | |
| if (fp == NULL) | |
| return 75; | |
| { | |
| char buf[10]; | |
| if (!(fread (buf, 1, 10, fp) == 9)) | |
| { fclose (fp); return 10; } | |
| if (!(memcmp (buf, "foogarsh!", 9) == 0)) | |
| { fclose (fp); return 11; } | |
| } | |
| if (!(fclose (fp) == 0)) | |
| return 12; | |
| /* The file's contents is now "foogarsh!". */ | |
| return 0; | |
| }]])], | |
| [gl_cv_func_ftello_works=yes], | |
| [gl_cv_func_ftello_works=no], [:]) | |
| ]) | |
| case "$gl_cv_func_ftello_works" in | |
| *yes) ;; | |
| *) | |
| REPLACE_FTELLO=1 | |
| AC_DEFINE([FTELLO_BROKEN_AFTER_SWITCHING_FROM_READ_TO_WRITE], [1], | |
| [Define to 1 if the system's ftello function has the Solaris bug.]) | |
| ;; | |
| esac | |
| fi | |
| if test $REPLACE_FTELLO = 0; then | |
| dnl Detect bug on macOS >= 10.15. | |
| gl_FUNC_UNGETC_WORKS | |
| if test $gl_ftello_broken_after_ungetc = yes; then | |
| REPLACE_FTELLO=1 | |
| AC_DEFINE([FTELLO_BROKEN_AFTER_UNGETC], [1], | |
| [Define to 1 if the system's ftello function has the macOS bug.]) | |
| fi | |
| fi | |
| fi | |
| ]) | |
| # Prerequisites of lib/ftello.c. | |
| AC_DEFUN([gl_PREREQ_FTELLO], | |
| [ | |
| if test $gl_cv_func_ftello != no; then | |
| AC_DEFINE([HAVE_FTELLO], [1], | |
| [Define to 1 if the system has the ftello function.]) | |
| fi | |
| dnl Native Windows has the function _ftelli64. mingw hides it, but mingw64 | |
| dnl makes it usable again. | |
| AC_CHECK_FUNCS([_ftelli64]) | |
| ]) |