]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libbsd/libbsd/lib/contrib/src/funopen.c
Update
[l4.git] / l4 / pkg / libbsd / libbsd / lib / contrib / src / funopen.c
1 /*
2  * Copyright © 2011, 2013 Guillem Jover
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
18  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 #include <sys/types.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32
33 #ifdef HAVE_FOPENCOOKIE
34 struct funopen_cookie {
35         void *orig_cookie;
36
37         int (*readfn)(void *cookie, char *buf, int size);
38         int (*writefn)(void *cookie, const char *buf, int size);
39         off_t (*seekfn)(void *cookie, off_t offset, int whence);
40         int (*closefn)(void *cookie);
41 };
42
43 static ssize_t
44 funopen_read(void *cookie, char *buf, size_t size)
45 {
46         struct funopen_cookie *cookiewrap = cookie;
47
48         if (cookiewrap->readfn == NULL) {
49                 errno = EBADF;
50                 return -1;
51         }
52
53         return cookiewrap->readfn(cookiewrap->orig_cookie, buf, size);
54 }
55
56 static ssize_t
57 funopen_write(void *cookie, const char *buf, size_t size)
58 {
59         struct funopen_cookie *cookiewrap = cookie;
60
61         if (cookiewrap->writefn == NULL)
62                 return EOF;
63
64         return cookiewrap->writefn(cookiewrap->orig_cookie, buf, size);
65 }
66
67 static int
68 funopen_seek(void *cookie, off64_t *offset, int whence)
69 {
70         struct funopen_cookie *cookiewrap = cookie;
71         off_t soff = *offset;
72
73         if (cookiewrap->seekfn == NULL) {
74                 errno = ESPIPE;
75                 return -1;
76         }
77
78         soff = cookiewrap->seekfn(cookiewrap->orig_cookie, soff, whence);
79         *offset = soff;
80
81         return *offset;
82 }
83
84 static int
85 funopen_close(void *cookie)
86 {
87         struct funopen_cookie *cookiewrap = cookie;
88         int rc;
89
90         if (cookiewrap->closefn == NULL)
91                 return 0;
92
93         rc = cookiewrap->closefn(cookiewrap->orig_cookie);
94
95         free(cookiewrap);
96
97         return rc;
98 }
99
100 FILE *
101 funopen(const void *cookie,
102         int (*readfn)(void *cookie, char *buf, int size),
103         int (*writefn)(void *cookie, const char *buf, int size),
104         off_t (*seekfn)(void *cookie, off_t offset, int whence),
105         int (*closefn)(void *cookie))
106 {
107         struct funopen_cookie *cookiewrap;
108         cookie_io_functions_t funcswrap = {
109                 .read = funopen_read,
110                 .write = funopen_write,
111                 .seek = funopen_seek,
112                 .close = funopen_close,
113         };
114         const char *mode;
115
116         if (readfn) {
117                 if (writefn == NULL)
118                         mode = "r";
119                 else
120                         mode = "r+";
121         } else if (writefn) {
122                 mode = "w";
123         } else {
124                 errno = EINVAL;
125                 return NULL;
126         }
127
128         cookiewrap = malloc(sizeof(*cookiewrap));
129         if (cookiewrap == NULL)
130                 return NULL;
131
132         cookiewrap->orig_cookie = (void *)cookie;
133         cookiewrap->readfn = readfn;
134         cookiewrap->writefn = writefn;
135         cookiewrap->seekfn = seekfn;
136         cookiewrap->closefn = closefn;
137
138         return fopencookie(cookiewrap, mode, funcswrap);
139 }
140 #else
141 #error "Function funopen() needs to be ported."
142 #endif