libctf: error handling
[deliverable/binutils-gdb.git] / libctf / ctf-subr.c
CommitLineData
60da9d95
NA
1/* Simple subrs.
2 Copyright (C) 2019 Free Software Foundation, Inc.
3
4 This file is part of libctf.
5
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
19
20#include <ctf-impl.h>
21#ifdef HAVE_MMAP
22#include <sys/mman.h>
23#endif
24#include <sys/types.h>
25#include <stdarg.h>
26#include <string.h>
27#include <unistd.h>
28
29static size_t _PAGESIZE _libctf_unused_;
30int _libctf_debug = 0; /* Debugging messages enabled. */
31
32_libctf_malloc_ void *
33ctf_data_alloc (size_t size)
34{
35 void *ret;
36
37#ifdef HAVE_MMAP
38 if (_PAGESIZE == 0)
39 _PAGESIZE = sysconf(_SC_PAGESIZE);
40
41 if (size > _PAGESIZE)
42 {
43 ret = mmap (NULL, size, PROT_READ | PROT_WRITE,
44 MAP_PRIVATE | MAP_ANON, -1, 0);
45 if (ret == MAP_FAILED)
46 ret = NULL;
47 }
48 else
49 ret = calloc (1, size);
50#else
51 ret = calloc (1, size);
52#endif
53 return ret;
54}
55
56void
57ctf_data_free (void *buf, size_t size _libctf_unused_)
58{
59#ifdef HAVE_MMAP
60 /* Must be the same as the check in ctf_data_alloc(). */
61
62 if (size > _PAGESIZE)
63 (void) munmap (buf, size);
64 else
65 free (buf);
66#else
67 free (buf);
68#endif
69}
70
71/* Private, read-only mmap from a file, with fallback to copying.
72
73 No handling of page-offset issues at all: the caller must allow for that. */
74
75_libctf_malloc_ void *
76ctf_mmap (size_t length, size_t offset, int fd)
77{
78 void *data;
79
80#ifdef HAVE_MMAP
81 data = mmap (NULL, length, PROT_READ, MAP_PRIVATE, fd, offset);
82 if (data == MAP_FAILED)
83 data = NULL;
84#else
85 if ((data = malloc (length)) != NULL)
86 {
87 if (ctf_pread (fd, data, length, offset) <= 0)
88 {
89 free (data);
90 data = NULL;
91 }
92 }
93#endif
94 return data;
95}
96
97void
98ctf_munmap (void *buf, size_t length _libctf_unused_)
99{
100#ifdef HAVE_MMAP
101 (void) munmap (buf, length);
102#else
103 free (buf);
104#endif
105}
106
107void
108ctf_data_protect (void *buf, size_t size)
109{
110#ifdef HAVE_MMAP
111 /* Must be the same as the check in ctf_data_alloc(). */
112
113 if (size > _PAGESIZE)
114 (void) mprotect (buf, size, PROT_READ);
115#endif
116}
117
118_libctf_malloc_ void *
119ctf_alloc (size_t size)
120{
121 return (malloc (size));
122}
123
124void
125ctf_free (void *buf)
126{
127 free (buf);
128}
129
130ssize_t
131ctf_pread (int fd, void *buf, ssize_t count, off_t offset)
132{
133 ssize_t len;
134 size_t acc = 0;
135 char *data = (char *) buf;
136
137#ifdef HAVE_PREAD
138 while (count > 0)
139 {
140 errno = 0;
141 if (((len = pread (fd, data, count, offset)) < 0) &&
142 errno != EINTR)
143 return len;
144 if (errno == EINTR)
145 continue;
146
147 acc += len;
148 if (len == 0) /* EOF. */
149 return acc;
150
151 count -= len;
152 offset += len;
153 data += len;
154 }
155 return acc;
156#else
157 off_t orig_off;
158
159 if ((orig_off = lseek (fd, 0, SEEK_CUR)) < 0)
160 return -1;
161 if ((lseek (fd, offset, SEEK_SET)) < 0)
162 return -1;
163
164 while (count > 0)
165 {
166 errno = 0;
167 if (((len = read (fd, data, count)) < 0) &&
168 errno != EINTR)
169 return len;
170 if (errno == EINTR)
171 continue;
172
173 acc += len;
174 if (len == 0) /* EOF. */
175 break;
176
177 count -= len;
178 data += len;
179 }
180 if ((lseek (fd, orig_off, SEEK_SET)) < 0)
181 return -1; /* offset is smashed. */
182#endif
183
184 return acc;
185}
186
187const char *
188ctf_strerror (int err)
189{
190 return (const char *) (strerror (err));
191}
192
193void
194libctf_init_debug (void)
195{
196 static int inited;
197 if (!inited)
198 {
199 _libctf_debug = getenv ("LIBCTF_DEBUG") != NULL;
200 inited = 1;
201 }
202}
203
204void ctf_setdebug (int debug)
205{
206 /* Ensure that libctf_init_debug() has been called, so that we don't get our
207 debugging-on-or-off smashed by the next call. */
208
209 libctf_init_debug();
210 _libctf_debug = debug;
211 ctf_dprintf ("CTF debugging set to %i\n", debug);
212}
213
214int ctf_getdebug (void)
215{
216 return _libctf_debug;
217}
218
219_libctf_printflike_ (1, 2)
220void ctf_dprintf (const char *format, ...)
221{
222 if (_libctf_debug)
223 {
224 va_list alist;
225
226 va_start (alist, format);
227 fflush (stdout);
228 (void) fputs ("libctf DEBUG: ", stderr);
229 (void) vfprintf (stderr, format, alist);
230 va_end (alist);
231 }
232}
This page took 0.030164 seconds and 4 git commands to generate.