1/*	$NetBSD: stdio.c,v 1.1 2024/02/18 20:57:57 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16#include <errno.h>
17#include <unistd.h>
18
19#include <isc/stat.h>
20#include <isc/stdio.h>
21#include <isc/util.h>
22
23#include "errno2result.h"
24
25isc_result_t
26isc_stdio_open(const char *filename, const char *mode, FILE **fp) {
27	FILE *f;
28
29	f = fopen(filename, mode);
30	if (f == NULL) {
31		return (isc__errno2result(errno));
32	}
33	*fp = f;
34	return (ISC_R_SUCCESS);
35}
36
37isc_result_t
38isc_stdio_close(FILE *f) {
39	int r;
40
41	r = fclose(f);
42	if (r == 0) {
43		return (ISC_R_SUCCESS);
44	} else {
45		return (isc__errno2result(errno));
46	}
47}
48
49isc_result_t
50isc_stdio_seek(FILE *f, off_t offset, int whence) {
51	int r;
52
53	r = fseeko(f, offset, whence);
54	if (r == 0) {
55		return (ISC_R_SUCCESS);
56	} else {
57		return (isc__errno2result(errno));
58	}
59}
60
61isc_result_t
62isc_stdio_tell(FILE *f, off_t *offsetp) {
63	off_t r;
64
65	REQUIRE(offsetp != NULL);
66
67	r = ftello(f);
68	if (r >= 0) {
69		*offsetp = r;
70		return (ISC_R_SUCCESS);
71	} else {
72		return (isc__errno2result(errno));
73	}
74}
75
76isc_result_t
77isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) {
78	isc_result_t result = ISC_R_SUCCESS;
79	size_t r;
80
81	clearerr(f);
82	r = fread(ptr, size, nmemb, f);
83	if (r != nmemb) {
84		if (feof(f)) {
85			result = ISC_R_EOF;
86		} else {
87			result = isc__errno2result(errno);
88		}
89	}
90	if (nret != NULL) {
91		*nret = r;
92	}
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	isc_result_t result = ISC_R_SUCCESS;
100	size_t r;
101
102	clearerr(f);
103	r = fwrite(ptr, size, nmemb, f);
104	if (r != nmemb) {
105		result = isc__errno2result(errno);
106	}
107	if (nret != NULL) {
108		*nret = r;
109	}
110	return (result);
111}
112
113isc_result_t
114isc_stdio_flush(FILE *f) {
115	int r;
116
117	r = fflush(f);
118	if (r == 0) {
119		return (ISC_R_SUCCESS);
120	} else {
121		return (isc__errno2result(errno));
122	}
123}
124
125/*
126 * OpenBSD has deprecated ENOTSUP in favor of EOPNOTSUPP.
127 */
128#if defined(EOPNOTSUPP) && !defined(ENOTSUP)
129#define ENOTSUP EOPNOTSUPP
130#endif /* if defined(EOPNOTSUPP) && !defined(ENOTSUP) */
131
132isc_result_t
133isc_stdio_sync(FILE *f) {
134	struct stat buf;
135	int r;
136
137	if (fstat(fileno(f), &buf) != 0) {
138		return (isc__errno2result(errno));
139	}
140
141	/*
142	 * Only call fsync() on regular files.
143	 */
144	if ((buf.st_mode & S_IFMT) != S_IFREG) {
145		return (ISC_R_SUCCESS);
146	}
147
148	r = fsync(fileno(f));
149	if (r == 0) {
150		return (ISC_R_SUCCESS);
151	} else {
152		return (isc__errno2result(errno));
153	}
154}
155