1/*
2 * Copyright (C) 2004, 2007, 2011-2013  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id$ */
19
20#include <config.h>
21
22#include <errno.h>
23#include <unistd.h>
24
25#include <isc/stdio.h>
26#include <isc/stat.h>
27#include <isc/util.h>
28
29#include "errno2result.h"
30
31isc_result_t
32isc_stdio_open(const char *filename, const char *mode, FILE **fp) {
33	FILE *f;
34
35	f = fopen(filename, mode);
36	if (f == NULL)
37		return (isc__errno2result(errno));
38	*fp = f;
39	return (ISC_R_SUCCESS);
40}
41
42isc_result_t
43isc_stdio_close(FILE *f) {
44	int r;
45
46	r = fclose(f);
47	if (r == 0)
48		return (ISC_R_SUCCESS);
49	else
50		return (isc__errno2result(errno));
51}
52
53isc_result_t
54isc_stdio_seek(FILE *f, off_t offset, int whence) {
55	int r;
56
57	r = fseeko(f, offset, whence);
58	if (r == 0)
59		return (ISC_R_SUCCESS);
60	else
61		return (isc__errno2result(errno));
62}
63
64isc_result_t
65isc_stdio_tell(FILE *f, off_t *offsetp) {
66	off_t r;
67
68	REQUIRE(offsetp != NULL);
69
70	r = ftello(f);
71	if (r >= 0) {
72		*offsetp = r;
73		return (ISC_R_SUCCESS);
74	} else
75		return (isc__errno2result(errno));
76}
77
78isc_result_t
79isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) {
80	isc_result_t result = ISC_R_SUCCESS;
81	size_t r;
82
83	clearerr(f);
84	r = fread(ptr, size, nmemb, f);
85	if (r != nmemb) {
86		if (feof(f))
87			result = ISC_R_EOF;
88		else
89			result = isc__errno2result(errno);
90	}
91	if (nret != NULL)
92		*nret = r;
93	return (result);
94}
95
96isc_result_t
97isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
98	       size_t *nret)
99{
100	isc_result_t result = ISC_R_SUCCESS;
101	size_t r;
102
103	clearerr(f);
104	r = fwrite(ptr, size, nmemb, f);
105	if (r != nmemb)
106		result = isc__errno2result(errno);
107	if (nret != NULL)
108		*nret = r;
109	return (result);
110}
111
112isc_result_t
113isc_stdio_flush(FILE *f) {
114	int r;
115
116	r = fflush(f);
117	if (r == 0)
118		return (ISC_R_SUCCESS);
119	else
120		return (isc__errno2result(errno));
121}
122
123/*
124 * OpenBSD has deprecated ENOTSUP in favor of EOPNOTSUPP.
125 */
126#if defined(EOPNOTSUPP) && !defined(ENOTSUP)
127#define ENOTSUP EOPNOTSUPP
128#endif
129
130isc_result_t
131isc_stdio_sync(FILE *f) {
132	int r;
133
134	r = fsync(fileno(f));
135	/*
136	 * fsync is not supported on sockets and pipes which
137	 * result in EINVAL / ENOTSUP.
138	 */
139	if (r == 0 || errno == EINVAL || errno == ENOTSUP)
140		return (ISC_R_SUCCESS);
141	else
142		return (isc__errno2result(errno));
143}
144
145