Commit | Line | Data |
---|---|---|
3719602c PC |
1 | /* Copyright (C) 2010-2020 The RetroArch team |
2 | * | |
3 | * --------------------------------------------------------------------------------------- | |
4 | * The following license statement only applies to this file (nbio_orbis.c). | |
5 | * --------------------------------------------------------------------------------------- | |
6 | * | |
7 | * Permission is hereby granted, free of charge, | |
8 | * to any person obtaining a copy of this software and associated documentation files (the "Software"), | |
9 | * to deal in the Software without restriction, including without limitation the rights to | |
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, | |
11 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |
16 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
21 | */ | |
22 | ||
23 | #include <file/nbio.h> | |
24 | ||
25 | #if defined(ORBIS) | |
26 | #include <stdio.h> | |
27 | #include <stdlib.h> | |
28 | #include <orbisFile.h> | |
29 | #include <unistd.h> | |
30 | #include <sys/fcntl.h> | |
31 | ||
32 | struct nbio_orbis_t | |
33 | { | |
34 | void* data; | |
35 | size_t progress; | |
36 | size_t len; | |
37 | int fd; | |
38 | unsigned int mode; | |
39 | /* | |
40 | * possible values: | |
41 | * NBIO_READ, NBIO_WRITE - obvious | |
42 | * -1 - currently doing nothing | |
43 | * -2 - the pointer was reallocated since the last operation | |
44 | */ | |
45 | signed char op; | |
46 | }; | |
47 | ||
48 | static void *nbio_orbis_open(const char * filename, unsigned int mode) | |
49 | { | |
50 | static const int o_flags[] = { O_RDONLY, O_RDWR | O_CREAT | O_TRUNC, | |
51 | O_RDWR, O_RDONLY, O_RDWR | O_CREAT | O_TRUNC }; | |
52 | void *buf = NULL; | |
53 | struct nbio_orbis_t* handle = NULL; | |
54 | size_t len = 0; | |
55 | int fd = orbisOpen(filename, o_flags[mode], 0644); | |
56 | ||
57 | if (fd < 0) | |
58 | return NULL; | |
59 | handle = (struct nbio_orbis_t*)malloc(sizeof(struct nbio_orbis_t)); | |
60 | ||
61 | if (!handle) | |
62 | goto error; | |
63 | ||
64 | handle->fd = fd; | |
65 | ||
66 | switch (mode) | |
67 | { | |
68 | case NBIO_WRITE: | |
69 | case BIO_WRITE: | |
70 | break; | |
71 | default: | |
72 | len=orbisLseek(handle->fd, 0, SEEK_END); | |
73 | orbisLseek(handle->fd, 0, SEEK_SET); | |
74 | break; | |
75 | } | |
76 | ||
77 | handle->mode = mode; | |
78 | ||
79 | if (len) | |
80 | buf = malloc(len); | |
81 | ||
82 | if (len && !buf) | |
83 | goto error; | |
84 | ||
85 | handle->data = buf; | |
86 | handle->len = len; | |
87 | handle->progress = handle->len; | |
88 | handle->op = -2; | |
89 | ||
90 | return handle; | |
91 | ||
92 | error: | |
93 | if (handle) | |
94 | free(handle); | |
95 | orbisClose(fd); | |
96 | return NULL; | |
97 | } | |
98 | ||
99 | static void nbio_orbis_begin_read(void *data) | |
100 | { | |
101 | ||
102 | struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data; | |
103 | if (!handle) | |
104 | return; | |
105 | ||
106 | if (handle->op >= 0) | |
107 | return; | |
108 | ||
109 | orbisLseek(handle->fd, 0, SEEK_SET); | |
110 | ||
111 | handle->op = NBIO_READ; | |
112 | handle->progress = 0; | |
113 | } | |
114 | ||
115 | static void nbio_orbis_begin_write(void *data) | |
116 | { | |
117 | struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data; | |
118 | if (!handle) | |
119 | return; | |
120 | ||
121 | if (handle->op >= 0) | |
122 | return; | |
123 | ||
124 | orbisLseek(handle->fd, 0, SEEK_SET); | |
125 | handle->op = NBIO_WRITE; | |
126 | handle->progress = 0; | |
127 | } | |
128 | ||
129 | static bool nbio_orbis_iterate(void *data) | |
130 | { | |
131 | size_t amount = 65536; | |
132 | struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data; | |
133 | ||
134 | if (!handle) | |
135 | return false; | |
136 | ||
137 | if (amount > handle->len - handle->progress) | |
138 | amount = handle->len - handle->progress; | |
139 | ||
140 | switch (handle->op) | |
141 | { | |
142 | case NBIO_READ: | |
143 | if (handle->mode == BIO_READ) | |
144 | amount = handle->len; | |
145 | break; | |
146 | case NBIO_WRITE: | |
147 | if (handle->mode == BIO_WRITE) | |
148 | { | |
149 | size_t written = 0; | |
150 | amount = handle->len; | |
151 | written = orbisWrite(handle->fd, (char*)handle->data, amount); | |
152 | ||
153 | if (written != amount) | |
154 | return false; | |
155 | } | |
156 | break; | |
157 | } | |
158 | ||
159 | handle->progress += amount; | |
160 | ||
161 | if (handle->progress == handle->len) | |
162 | handle->op = -1; | |
163 | return (handle->op < 0); | |
164 | } | |
165 | ||
166 | static void nbio_orbis_resize(void *data, size_t len) | |
167 | { | |
168 | struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data; | |
169 | if (!handle) | |
170 | return; | |
171 | ||
172 | if (handle->op >= 0) | |
173 | return; | |
174 | if (len < handle->len) | |
175 | return; | |
176 | ||
177 | handle->len = len; | |
178 | handle->data = realloc(handle->data, handle->len); | |
179 | handle->op = -1; | |
180 | handle->progress = handle->len; | |
181 | } | |
182 | ||
183 | static void *nbio_orbis_get_ptr(void *data, size_t* len) | |
184 | { | |
185 | struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data; | |
186 | if (!handle) | |
187 | return NULL; | |
188 | if (len) | |
189 | *len = handle->len; | |
190 | if (handle->op == -1) | |
191 | return handle->data; | |
192 | return NULL; | |
193 | } | |
194 | ||
195 | static void nbio_orbis_cancel(void *data) | |
196 | { | |
197 | struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data; | |
198 | if (!handle) | |
199 | return; | |
200 | handle->op = -1; | |
201 | handle->progress = handle->len; | |
202 | } | |
203 | ||
204 | static void nbio_orbis_free(void *data) | |
205 | { | |
206 | struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data; | |
207 | if (!handle) | |
208 | return; | |
209 | ||
210 | if (handle->op >= 0) | |
211 | return; | |
212 | ||
213 | orbisClose(handle->fd); | |
214 | free(handle->data); | |
215 | ||
216 | handle->data = NULL; | |
217 | free(handle); | |
218 | } | |
219 | ||
220 | nbio_intf_t nbio_orbis = { | |
221 | nbio_orbis_open, | |
222 | nbio_orbis_begin_read, | |
223 | nbio_orbis_begin_write, | |
224 | nbio_orbis_iterate, | |
225 | nbio_orbis_resize, | |
226 | nbio_orbis_get_ptr, | |
227 | nbio_orbis_cancel, | |
228 | nbio_orbis_free, | |
229 | "nbio_orbis", | |
230 | }; | |
231 | #endif |