Improve OpenBSD support: Allow faster VMA determination.
[libsigsegv/ericb.git] / src / stackvma-rofile.c
blobaa2e5c15521debe1a8a51f283596ee09a5bf11b7
1 /* Buffered read-only streams.
2 Copyright (C) 2008 Bruno Haible <bruno@clisp.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 #include <errno.h> /* errno, EINTR */
19 #include <fcntl.h> /* O_RDONLY */
20 #include <stddef.h> /* size_t */
21 #include <unistd.h> /* read, close */
23 /* Buffered read-only streams.
24 We cannot use <stdio.h> here, because fopen() calls malloc(), and a malloc()
25 call may have been interrupted.
26 The buffer cannot be too large, because this can be called when we are
27 in the context of an alternate stack of just SIGSTKSZ bytes. */
29 struct rofile
31 int fd;
32 size_t position;
33 size_t filled;
34 int eof_seen;
35 char buffer[1024];
38 /* Open a read-only file stream. */
39 static int
40 rof_open (struct rofile *rof, const char *filename)
42 int fd = open (filename, O_RDONLY);
43 if (fd < 0)
44 return -1;
45 rof->fd = fd;
46 rof->position = 0;
47 rof->filled = 0;
48 rof->eof_seen = 0;
49 return 0;
52 /* Return the next byte from a read-only file stream without consuming it,
53 or -1 at EOF. */
54 static int
55 rof_peekchar (struct rofile *rof)
57 if (rof->position == rof->filled)
59 if (rof->eof_seen)
60 return -1;
61 else
62 for (;;)
64 int n = read (rof->fd, rof->buffer, sizeof (rof->buffer));
65 #ifdef EINTR
66 if (n < 0 && errno == EINTR)
67 continue;
68 #endif
69 if (n <= 0)
71 rof->eof_seen = 1;
72 return -1;
74 rof->filled = n;
75 rof->position = 0;
76 break;
79 return (unsigned char) rof->buffer[rof->position];
82 /* Return the next byte from a read-only file stream, or -1 at EOF. */
83 static int
84 rof_getchar (struct rofile *rof)
86 int c = rof_peekchar (rof);
87 if (c >= 0)
88 rof->position++;
89 return c;
92 /* Parse an unsigned hexadecimal number from a read-only file stream. */
93 static int
94 rof_scanf_lx (struct rofile *rof, unsigned long *valuep)
96 unsigned long value = 0;
97 unsigned int numdigits = 0;
98 for (;;)
100 int c = rof_peekchar (rof);
101 if (c >= '0' && c <= '9')
102 value = (value << 4) + (c - '0');
103 else if (c >= 'A' && c <= 'F')
104 value = (value << 4) + (c - 'A' + 10);
105 else if (c >= 'a' && c <= 'f')
106 value = (value << 4) + (c - 'a' + 10);
107 else
108 break;
109 rof_getchar (rof);
110 numdigits++;
112 if (numdigits == 0)
113 return -1;
114 *valuep = value;
115 return 0;
118 /* Close a read-only file stream. */
119 static void
120 rof_close (struct rofile *rof)
122 close (rof->fd);