scclib
Stable Cloud Computing C++ Library
safe_clib.cc
Go to the documentation of this file.
1 /*
2 BSD 3-Clause License
3 
4 Copyright (c) 2022, Stable Cloud Computing, Inc.
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 
9 1. Redistributions of source code must retain the above copyright notice, this
10  list of conditions and the following disclaimer.
11 
12 2. Redistributions in binary form must reproduce the above copyright notice,
13  this list of conditions and the following disclaimer in the documentation
14  and/or other materials provided with the distribution.
15 
16 3. Neither the name of the copyright holder nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <util/safe_clib.h>
32 #include <system_error>
33 #include <sstream>
34 #include <stdarg.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <sys/wait.h>
40 #include <cstdio>
41 
47 using namespace scc::util;
48 
49 int scc::util::safe_truncate(const char *path, off_t length)
50 {
51  int r;
52  do
53  {
54  r = ::truncate(path, length);
55  }
56  while (r == -1 && errno == EINTR);
57  return r;
58 }
59 
60 int scc::util::safe_truncate_throw(const char *path, off_t length)
61 {
62  int r = truncate(path, length);
63  if (r == -1)
64  {
65  std::stringstream st;
66  st << "truncate(" << path << "," << length << ")";
67  throw std::system_error(errno, std::system_category(), st.str());
68  }
69  return r;
70 }
71 
72 int scc::util::safe_ftruncate(int fd, off_t length)
73 {
74  int r;
75  do
76  {
77  r = ::ftruncate(fd, length);
78  }
79  while (r == -1 && errno == EINTR);
80  return r;
81 }
82 
83 int scc::util::safe_ftruncate_throw(int fd, off_t length)
84 {
85  int r = ftruncate(fd, length);
86  if (r == -1)
87  {
88  std::stringstream st;
89  st << "ftruncate(" << fd << "," << length << ")";
90  throw std::system_error(errno, std::system_category(), st.str());
91  }
92  return r;
93 }
94 
96 {
97  int r;
98  do
99  {
100  r = ::close(fd);
101  }
102  while (r == -1 && errno == EINTR);
103  return r;
104 }
105 
107 {
108  int r = safe_close(fd);
109  if (r == -1)
110  {
111  std::stringstream st;
112  st << "close(" << fd << ")";
113  throw std::system_error(errno, std::system_category(), st.str());
114  }
115  return r;
116 }
117 
118 ssize_t scc::util::safe_read(int fd, void *buf, size_t count)
119 {
120  ssize_t r;
121  do
122  {
123  r = ::read(fd, buf, count);
124  }
125  while (r == -1 && errno == EINTR);
126  return r;
127 }
128 
129 ssize_t scc::util::safe_read_throw(int fd, void *buf, size_t count)
130 {
131  ssize_t r = safe_read(fd, buf, count);
132  if (r == -1)
133  {
134  std::stringstream st;
135  st << "read(" << fd << ", ...)";
136  throw std::system_error(errno, std::system_category(), st.str());
137  }
138  return r;
139 }
140 
141 ssize_t scc::util::safe_write(int fd, const void *buf, size_t count)
142 {
143  ssize_t r;
144  do
145  {
146  r = ::write(fd, buf, count);
147  }
148  while (r == -1 && errno == EINTR);
149  return r;
150 }
151 
152 ssize_t scc::util::safe_write_throw(int fd, const void *buf, size_t count)
153 {
154  ssize_t r = safe_write(fd, buf, count);
155  if (r == -1)
156  {
157  std::stringstream st;
158  st << "write(" << fd << ", ...)";
159  throw std::system_error(errno, std::system_category(), st.str());
160  }
161  return r;
162 }
163 
164 int scc::util::safe_dup(int oldfd)
165 {
166  int r;
167  do
168  {
169  r = ::dup(oldfd);
170  }
171  while (r == -1 && errno == EINTR);
172  return r;
173 }
174 
176 {
177  int r = safe_dup(oldfd);
178  if (r == -1)
179  {
180  std::stringstream st;
181  st << "dup(" << oldfd << ")";
182  throw std::system_error(errno, std::system_category(), st.str());
183  }
184  return r;
185 }
186 
187 int scc::util::safe_dup2(int oldfd, int newfd)
188 {
189  int r;
190  do
191  {
192  r = ::dup2(oldfd, newfd);
193  }
194  while (r == -1 && (errno == EINTR||errno == EBUSY));
195  return r;
196 }
197 
198 int scc::util::safe_dup2_throw(int oldfd, int newfd)
199 {
200  int r = safe_dup2(oldfd, newfd);
201  if (r == -1)
202  {
203  std::stringstream st;
204  st << "dup2(" << oldfd << "," << newfd << ")";
205  throw std::system_error(errno, std::system_category(), st.str());
206  }
207  return r;
208 }
209 
210 int scc::util::safe_open(const char *pathname, int flags)
211 {
212  int r;
213  do
214  {
215  r = ::open(pathname, flags);
216  }
217  while (r == -1 && errno == EINTR);
218  return r;
219 }
220 
221 int scc::util::safe_open_throw(const char *pathname, int flags)
222 {
223  int r = safe_open(pathname, flags);
224  if (r == -1)
225  {
226  std::stringstream st;
227  st << "open(" << pathname << "," << flags << ")";
228  throw std::system_error(errno, std::system_category(), st.str());
229  }
230  return r;
231 }
232 
233 int scc::util::safe_open(const char *pathname, int flags, mode_t mode)
234 {
235  int r;
236  do
237  {
238  r = ::open(pathname, flags, mode);
239  }
240  while (r == -1 && errno == EINTR);
241  return r;
242 }
243 
244 int scc::util::safe_open_throw(const char *pathname, int flags, mode_t mode)
245 {
246  int r = safe_open(pathname, flags, mode);
247  if (r == -1)
248  {
249  std::stringstream st;
250  st << "open(" << pathname << "," << flags << "," << mode << ")";
251  throw std::system_error(errno, std::system_category(), st.str());
252  }
253  return r;
254 }
255 
256 FILE* scc::util::safe_fopen(const char *pathname, const char *mode)
257 {
258  FILE* r;
259  do
260  {
261  r = ::fopen(pathname, mode);
262  }
263  while (r == nullptr && errno == EINTR);
264  return r;
265 }
266 
267 FILE* scc::util::safe_fopen_throw(const char *pathname, const char *mode)
268 {
269  FILE* r = safe_fopen(pathname, mode);
270  if (r == nullptr)
271  {
272  std::stringstream st;
273  st << "fopen(" << pathname << "," << mode << ")";
274  throw std::system_error(errno, std::system_category(), st.str());
275  }
276  return r;
277 }
278 
279 int scc::util::safe_fclose(FILE* stream)
280 {
281  int r;
282  do
283  {
284  r = ::fclose(stream);
285  }
286  while (r == -1 && errno == EINTR);
287  return r;
288 }
289 
291 {
292  int r = safe_fclose(stream);
293  if (r == -1)
294  {
295  std::stringstream st;
296  st << "fclose()";
297  throw std::system_error(errno, std::system_category(), st.str());
298  }
299  return r;
300 }
301 
302 static int safe_vfscanf(FILE *stream, const char *format, va_list ap)
303 {
304  int r;
305  do
306  {
307  if (ferror(stream) && errno == EINTR)
308  {
309  clearerr(stream);
310  }
311  r = ::vfscanf(stream, format, ap);
312  }
313  while (r == EOF && ferror(stream) && errno == EINTR);
314  return r;
315 }
316 
317 int scc::util::safe_fscanf(FILE *stream, const char *format, ...)
318 {
319  va_list va;
320  va_start(va, format);
321  int r = safe_vfscanf(stream, format, va);
322  va_end(va);
323  return r;
324 }
325 
326 int scc::util::safe_fscanf_throw(FILE *stream, const char *format, ...)
327 {
328  va_list va;
329  va_start(va, format);
330  int r = safe_vfscanf(stream, format, va);
331  va_end(va);
332  if (r == EOF && ferror(stream))
333  {
334  std::stringstream st;
335  st << "fscanf()";
336  throw std::system_error(errno, std::system_category(), st.str());
337  }
338  return r;
339 }
340 
341 ssize_t scc::util::safe_getline(char **lineptr, size_t *n, FILE *stream)
342 {
343  ssize_t r;
344  do
345  {
346  r = ::getline(lineptr, n, stream);
347  }
348  while (r == -1 && errno == EINTR);
349  return r;
350 }
351 
352 ssize_t scc::util::safe_getline_throw(char **lineptr, size_t *n, FILE *stream)
353 {
354  ssize_t r = safe_getline(lineptr, n, stream);
355  if (r == -1)
356  {
357  std::stringstream st;
358  st << "getline()";
359  throw std::system_error(errno, std::system_category(), st.str());
360  }
361  return r;
362 }
363 
364 int scc::util::safe_wait(int *wstatus)
365 {
366  return safe_waitpid(-1, wstatus, 0);
367 }
368 
369 int scc::util::safe_waitpid(pid_t pid, int *wstatus, int options)
370 {
371  int r;
372  do
373  {
374  r = ::waitpid(pid, wstatus, options);
375  }
376  while (r == -1 && errno == EINTR);
377  return r;
378 }
379 
380 int scc::util::safe_wait_throw(int *wstatus)
381 {
382  return safe_waitpid_throw(-1, wstatus, 0);
383 }
384 
385 int scc::util::safe_waitpid_throw(pid_t pid, int *wstatus, int options)
386 {
387  int r = safe_waitpid(pid, wstatus, options);
388  if (r == -1)
389  {
390  std::stringstream st;
391  st << "waitpid(" << pid << ")";
392  throw std::system_error(errno, std::system_category(), st.str());
393  }
394  return r;
395 }
int safe_close(int fd)
Signal safe close.
Definition: safe_clib.cc:95
int safe_dup2_throw(int oldfd, int newfd)
Signal safe dup2, throws system_error on error.
Definition: safe_clib.cc:198
ssize_t safe_read_throw(int fd, void *buf, size_t count)
Signal safe read, throws system_error on error.
Definition: safe_clib.cc:129
int safe_wait_throw(int *wstatus)
Signal safe wait, throws system_error on error.
Definition: safe_clib.cc:380
int safe_fclose_throw(FILE *stream)
Signal safe fclose, throws system_error on error.
Definition: safe_clib.cc:290
ssize_t safe_write_throw(int fd, const void *buf, size_t count)
Signal safe write, throws system_error on error.
Definition: safe_clib.cc:152
FILE * safe_fopen(const char *pathname, const char *mode)
Signal safe fopen.
Definition: safe_clib.cc:256
ssize_t safe_read(int fd, void *buf, size_t count)
Signal safe read.
Definition: safe_clib.cc:118
int safe_wait(int *wstatus)
Signal safe wait.
Definition: safe_clib.cc:364
ssize_t safe_write(int fd, const void *buf, size_t count)
Signal safe write.
Definition: safe_clib.cc:141
int safe_dup_throw(int oldfd)
Signal safe dup, throws system_error on error.
Definition: safe_clib.cc:175
ssize_t safe_getline_throw(char **lineptr, size_t *n, FILE *stream)
Signal safe getline, throw on error.
Definition: safe_clib.cc:352
ssize_t safe_getline(char **lineptr, size_t *n, FILE *stream)
Signal safe getline.
Definition: safe_clib.cc:341
int safe_fscanf(FILE *stream, const char *format,...)
Signal safe fscanf.
Definition: safe_clib.cc:317
int safe_close_throw(int fd)
Signal safe close, throws system_error on error.
Definition: safe_clib.cc:106
int safe_waitpid_throw(pid_t pid, int *wstatus, int options)
Signal safe waitpid, throws system_error on error.
Definition: safe_clib.cc:385
int safe_ftruncate_throw(int fd, off_t length)
Signal safe ftruncate, throw on error.
Definition: safe_clib.cc:83
int safe_fclose(FILE *stream)
Signal safe fclose.
Definition: safe_clib.cc:279
int safe_open_throw(const char *pathname, int flags)
Signal safe open, throws system_error on error.
Definition: safe_clib.cc:221
int safe_open(const char *pathname, int flags)
Signal safe open.
Definition: safe_clib.cc:210
int safe_truncate(const char *path, off_t length)
Signal safe truncate.
Definition: safe_clib.cc:49
int safe_waitpid(pid_t pid, int *wstatus, int options)
Signal safe waitpid.
Definition: safe_clib.cc:369
int safe_dup2(int oldfd, int newfd)
Signal safe dup2.
Definition: safe_clib.cc:187
int safe_fscanf_throw(FILE *stream, const char *format,...)
Signal safe fscanf, throw on error.
Definition: safe_clib.cc:326
int safe_truncate_throw(const char *path, off_t length)
Signal safe truncate, throw on error.
Definition: safe_clib.cc:60
int safe_ftruncate(int fd, off_t length)
Signal safe ftruncate.
Definition: safe_clib.cc:72
int safe_dup(int oldfd)
Signal safe dup.
Definition: safe_clib.cc:164
FILE * safe_fopen_throw(const char *pathname, const char *mode)
Signal safe fopen, throws system_error on error.
Definition: safe_clib.cc:267
Signal-safe C library wrapper.