- Subject: libc/1510: getc on /dev/null sets errno to 25
- From: eric_backus at agilent dot com
- Date: Wed Jan 5 14:30:03 2000
Topics:
libc/1510: getc on /dev/null sets errno to 25
----------------------------------------------------------------------
Date: Tue, 4 Jan 2000 16:19:54 -0500
From: eric_backus@agilent.com
To: bugs@gnu.org
Subject: libc/1510: getc on /dev/null sets errno to 25
Message-Id: <200001042119.QAA03940@delysid.gnu.org>
>Number: 1510
>Category: libc
>Synopsis: getc on /dev/null sets errno to 25
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: libc-gnats
>State: open
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Tue Jan 04 16:20:02 EST 2000
>Last-Modified:
>Originator: eric_backus@agilent.com
>Organization:
net
>Release: 2.1.2
>Environment:
I'm running Linux 2.2.12 on a Gateway 2000 200MHz Pentium Pro.
I have glibc 2.1.2, and my compiler is egcs 2.91.66. This is all taken from
the standard RedHat 6.1 distribution.
>Description:
If I fopen() /dev/null, and then try to read a character from it with getc,
the operation correctly returns EOF, but as a side effect it also sets errno.
I believe this is incorrect - ferror reports that nothing is wrong, so why
should errno be set? Also, for what it's worth, I tried this on HP-UX 10.20,
and it did not mess with errno.
>How-To-Repeat:
/* This program demonstrates a bug on my machine, where calling getc
on a stdio stream that is connected to /dev/null modifies errno.
On my machine, I end up with errno = 25 ("Inappropriate ioctl for
device").
Note that ferror does NOT get set in this case. Furthermore, if I
use an empty file rather than /dev/null, errno does not get set.
My machine is a Gateway2000 200MHz Pentium Pro, running Linux
2.2.12 with glibc 2.1.2, and my compiler is egcs 2.91.66, all taken
directly from the RedHat 6.1 distribution. */
#include <errno.h> /* For errno */
#include <stdio.h> /* For printf, fprintf, fopen, getc */
#include <stdlib.h> /* For EXIT_SUCCESS, EXIT_FAILURE */
#include <string.h> /* For strerror */
int
main(int argc, char **argv)
{
FILE *fp;
int c, verbose;
/* Decide if we should be verbose */
verbose = 0;
if (argc > 2)
{
(void) fprintf(stderr, "Usage: %s [-v]\n\t-v: verbose\n", argv[0]);
return EXIT_FAILURE;
}
if (argc > 1)
{
if (strcmp(argv[1], "-v") != 0)
{
(void) fprintf(stderr, "Usage: %s [-v]\n\t-v: verbose\n", argv[0]);
return EXIT_FAILURE;
}
verbose = 1;
}
/* Verify that errno is zero at start of program */
if (verbose)
(void) printf("Checking errno at start of program\n");
if (errno != 0)
{
(void) fprintf(stderr, "%s: errno %d after read from /dev/null\n",
argv[0], errno);
(void) fprintf(stderr, "%s: (\"%s\")\n", argv[0], strerror(errno));
return EXIT_FAILURE;
}
/* Open /dev/null for reading */
if (verbose)
(void) printf("Openning /dev/null\n");
fp = fopen("/dev/null", "r");
if (fp == NULL)
{
(void) fprintf(stderr, "%s: fopen(\"/dev/null\", \"r\") failed\n",
argv[0]);
return EXIT_FAILURE;
}
/* Verify that ferror returns zero */
if (verbose)
(void) printf("Checking ferror after fopen\n");
if (ferror(fp))
{
(void) fprintf(stderr, "%s: ferror after fopen\n", argv[0]);
return EXIT_FAILURE;
}
/* Verify that errno is still zero */
if (verbose)
(void) printf("Checking errno after fopen\n");
if (errno != 0)
{
(void) fprintf(stderr, "%s: errno %d after read from /dev/null\n",
argv[0], errno);
(void) fprintf(stderr, "%s: (\"%s\")\n", argv[0], strerror(errno));
return EXIT_FAILURE;
}
/* Attempt to read from /dev/null */
if (verbose)
(void) printf("Attempting to read from /dev/null\n");
c = getc(fp);
if (c != EOF)
{
(void) fprintf(stderr, "%s: successful read from /dev/null?\n",
argv[0]);
return EXIT_FAILURE;
}
/* Verify that ferror returns zero */
if (verbose)
(void) printf("Checking ferror after read from /dev/null\n");
if (ferror(fp))
{
(void) fprintf(stderr, "%s: ferror after getc\n", argv[0]);
return EXIT_FAILURE;
}
/* Verify that errno is still zero */
if (verbose)
(void) printf("Checking errno after read from /dev/null\n");
if (errno != 0)
{
(void) fprintf(stderr, "%s: errno %d after read from /dev/null\n",
argv[0], errno);
(void) fprintf(stderr, "%s: (\"%s\")\n", argv[0], strerror(errno));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}%0
>Fix:
>Audit-Trail:
>Unformatted:
------------------------------
End of forwardH-AxWv Digest
***************************