The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
fopencookie.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Wrap funopen to provide an fopencookie compatible interface on systems that don't support it
18 *
19 * @file src/lib/util/fopencookie.c
20 *
21 * @copyright 2019 The FreeRADIUS server project
22 * @copyright 2019 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 */
24RCSID("$Id: 348c07f011aa98ac101bfca7ec5a73628297a13d $")
25
26#ifndef HAVE_FOPENCOOKIE
27#include <freeradius-devel/util/talloc.h>
28#include <stdio.h>
29#include "fopencookie.h"
30
31#define NEED_READ 0x01
32#define NEED_WRITE 0x02
33#define NEED_SEEK 0x04
34
35/** Holds the fopencookie function pointers plus the funopen cookie
36 *
37 */
38typedef struct {
39 void *cookie; //!< Original cookie passed to fopencookie
40 cookie_io_functions_t io_funcs; //!< Fopencookie callbacks (which we wrap)
42
43
44/** Wrap fopencookie read function
45 *
46 */
47static int _read(void *c, char *buf, int n)
48{
49 fr_funopen_cookie_t *oc = talloc_get_type_abort(c, fr_funopen_cookie_t);
50
51 return (int)oc->io_funcs.read(oc->cookie, buf, (size_t)n);
52}
53
54/** Wrap fopencookie write function
55 *
56 */
57static int _write(void *c, const char *buf, int n)
58{
59 fr_funopen_cookie_t *oc = talloc_get_type_abort(c, fr_funopen_cookie_t);
60
61 return (int)oc->io_funcs.write(oc->cookie, buf, (size_t)n);
62}
63
64/** Wrap fopencookie seek function
65 *
66 */
67static fpos_t _seek(void *c, fpos_t offset, int whence)
68{
69 fr_funopen_cookie_t *oc = talloc_get_type_abort(c, fr_funopen_cookie_t);
70 int ret;
71
72 /*
73 * fopencookie seek cb should return
74 * and update offset to be the new position,
75 * or not zero and leave offset untouched.
76 *
77 * funopen seek cb should return -1 for an error
78 * or the new offset on success.
79 */
80 ret = oc->io_funcs.seek(oc->cookie, (off64_t *)&offset, whence);
81 if (ret != 0) return -1;
82
83 return offset;
84}
85
86/** Wrap fopencookie close function and free our fr_funopen_cookie_t
87 *
88 */
89static int _close(void *c)
90{
91 fr_funopen_cookie_t *oc = talloc_get_type_abort(c, fr_funopen_cookie_t);
92 int ret = oc->io_funcs.close ? oc->io_funcs.close(oc->cookie) : 0;
93
94 talloc_free(oc);
95
96 return ret;
97}
98
99FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t io_funcs)
100{
102 int need = 0;
103 FILE *f;
104 char const *p;
105
106 /*
107 * Process mode string as described by `man fopen`
108 */
109 for (p = mode; *p != '\0'; p++) {
110 switch (*p) {
111 case 'r':
112 need |= NEED_READ;
113
114 if (p[1] == 'b') p++; /* Skip binary */
115 if (p[1] == '+') {
116 p++;
117 need |= NEED_WRITE;
118 continue;
119 }
120 continue;
121
122 case 'w':
123 need |= NEED_WRITE;
124
125 if (p[1] == 'b') p++; /* Skip binary */
126 if (p[1] == '+') {
127 p++;
128 need |= NEED_READ;
129 continue;
130 }
131 continue;
132
133 case 'a':
134 need |= (NEED_SEEK | NEED_WRITE);
135
136 if (p[1] == 'b') p++; /* Skip binary */
137 if (p[1] == '+') {
138 p++;
139 need |= NEED_READ;
140 continue;
141 }
142 continue;
143
144 /*
145 * 'b' is also allowed as the last char
146 */
147 case 'b':
148 if (p[1] != '\0') {
149 invalid_arg:
150 errno = EINVAL;
151 return NULL;
152 }
153 continue; /* Loop will exit next iteration */
154
155 default:
156 goto invalid_arg;
157 }
158 }
159
160 if ((need & NEED_READ) && !io_funcs.read) goto invalid_arg;
161 if ((need & NEED_WRITE) && !io_funcs.write) goto invalid_arg;
162 if ((need & NEED_SEEK) && !io_funcs.seek) goto invalid_arg;
163
164 oc = talloc_zero(NULL, fr_funopen_cookie_t);
165 if (!oc) {
166 errno = ENOMEM;
167 return NULL;
168 }
169
170 oc->io_funcs = io_funcs;
171 oc->cookie = cookie;
172
173 f = funopen(oc,
174 oc->io_funcs.read ? _read : NULL,
175 oc->io_funcs.write ? _write : NULL,
176 oc->io_funcs.seek ? _seek : NULL,
177 _close);
178 if (!f) {
179 talloc_free(oc);
180 return NULL;
181 }
182
183 if (need & NEED_SEEK) {
184 if (fseek(f, 0L, SEEK_END) < 0) {
185 fclose(f);
186 talloc_free(oc);
187 return NULL;
188 }
189 }
190
191 return f;
192}
193#endif
int n
Definition acutest.h:577
#define RCSID(id)
Definition build.h:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
static int _write(void *c, const char *buf, int n)
Wrap fopencookie write function.
Definition fopencookie.c:57
#define NEED_READ
Definition fopencookie.c:31
static int _close(void *c)
Wrap fopencookie close function and free our fr_funopen_cookie_t.
Definition fopencookie.c:89
static fpos_t _seek(void *c, fpos_t offset, int whence)
Wrap fopencookie seek function.
Definition fopencookie.c:67
FILE * fopencookie(void *cookie, const char *mode, cookie_io_functions_t io_funcs)
Definition fopencookie.c:99
void * cookie
Original cookie passed to fopencookie.
Definition fopencookie.c:39
static int _read(void *c, char *buf, int n)
Wrap fopencookie read function.
Definition fopencookie.c:47
#define NEED_SEEK
Definition fopencookie.c:33
#define NEED_WRITE
Definition fopencookie.c:32
cookie_io_functions_t io_funcs
Fopencookie callbacks (which we wrap)
Definition fopencookie.c:40
Provide missing types for fopencookie on systems that don't support it.
cookie_close_function_t close
Definition fopencookie.h:55
cookie_seek_function_t seek
Definition fopencookie.h:54
cookie_read_function_t read
Definition fopencookie.h:52
cookie_write_function_t write
Definition fopencookie.h:53
talloc_free(reap)
static const trunk_io_funcs_t io_funcs
Definition bio.c:2416