source: roaraudio/libroar/vio.c @ 5377:72f1d48ff502

Last change on this file since 5377:72f1d48ff502 was 5377:72f1d48ff502, checked in by phi, 12 years ago

Removed legacy functions (Closes: #130):

  • roar_vio_init_calls(),
  • roar_vio_set_inst(),
  • roar_vio_set_fh() and roar_vio_get_fh(),
  • roar_simple_new_stream_obj().
File size: 18.9 KB
Line 
1//vio.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#define _LIBROAR_NOATTR_TO_STATIC /* ignore warnings for TO_STATIC functions */
37#include "libroar.h"
38
39#ifdef ROAR_HAVE_H_SYS_IOCTL
40#include <sys/ioctl.h>
41#endif
42
43#ifdef ROAR_HAVE_IO_POSIX
44#define _CAN_OPERATE
45#endif
46
47int roar_vio_clear_calls (struct roar_vio_calls * calls) {
48 if ( calls == NULL ) {
49  roar_err_set(ROAR_ERROR_FAULT);
50  return -1;
51 }
52
53 memset((void*)calls, 0, sizeof(struct roar_vio_calls));
54
55 return 0;
56}
57
58static int roar_vio_get_fh   (struct roar_vio_calls * vio) {
59 if ( vio == NULL ) {
60  roar_err_set(ROAR_ERROR_FAULT);
61  return -1;
62 }
63
64 return ((int)(ROAR_INSTINT)vio->inst) - 1;
65}
66
67
68ssize_t roar_vio_read (struct roar_vio_calls * vio, void *buf, size_t count) {
69 ssize_t ret;
70
71 ROAR_DBG("roar_vio_read(vio=%p, buf=%p, count=%u) = ?", vio, buf, (unsigned int)count);
72
73 if ( vio == NULL ) {
74  roar_err_set(ROAR_ERROR_FAULT);
75  return -1;
76 }
77
78 if ( vio->read == NULL ) {
79  roar_err_set(ROAR_ERROR_NOSYS);
80  return -1;
81 }
82
83 roar_err_clear_all();
84 ret = vio->read(vio, buf, count);
85 roar_err_update();
86
87 return ret;
88}
89
90ssize_t roar_vio_write(struct roar_vio_calls * vio, void *buf, size_t count) {
91 ssize_t ret;
92
93 ROAR_DBG("roar_vio_write(vio=%p, buf=%p, count=%u) = ?", vio, buf, (unsigned int)count);
94
95 if ( vio == NULL ) {
96  roar_err_set(ROAR_ERROR_FAULT);
97  return -1;
98 }
99
100 if ( vio->write == NULL ) {
101  roar_err_set(ROAR_ERROR_NOSYS);
102  return -1;
103 }
104
105 roar_err_clear_all();
106 ret = vio->write(vio, buf, count);
107 roar_err_update();
108
109 return ret;
110}
111
112roar_off_t   roar_vio_lseek(struct roar_vio_calls * vio, roar_off_t offset, int whence) {
113 roar_off_t ret;
114
115 ROAR_DBG("roar_vio_lseek(vio=%p, offset=%li, whence=%i) = ?", vio, (long int)offset, whence);
116
117 if ( vio == NULL ) {
118  roar_err_set(ROAR_ERROR_FAULT);
119  return -1;
120 }
121
122 if ( vio->lseek == NULL ) {
123  roar_err_set(ROAR_ERROR_NOSYS);
124  return -1;
125 }
126
127 roar_err_clear_all();
128 ret = vio->lseek(vio, offset, whence);
129 roar_err_update();
130
131 return ret;
132}
133
134int     roar_vio_nonblock(struct roar_vio_calls * vio, int state) {
135 ROAR_DBG("roar_vio_nonblock(vio=%p, state=%i) = ?", vio, state);
136
137 if ( vio == NULL ) {
138  roar_err_set(ROAR_ERROR_FAULT);
139  return -1;
140 }
141
142 return roar_vio_ctl(vio, ROAR_VIO_CTL_NONBLOCK, &state);
143}
144
145int     roar_vio_sync    (struct roar_vio_calls * vio) {
146 int ret;
147
148 ROAR_DBG("roar_vio_sync(vio=%p) = ?", vio);
149
150 if ( vio == NULL ) {
151  roar_err_set(ROAR_ERROR_FAULT);
152  return -1;
153 }
154
155 if ( vio->sync == NULL ) {
156  roar_err_set(ROAR_ERROR_NOSYS);
157  return -1;
158 }
159
160 roar_err_clear_all();
161 ret = vio->sync(vio);
162 roar_err_update();
163
164 return ret;
165}
166
167int     roar_vio_ctl     (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
168 int ret;
169
170 ROAR_DBG("roar_vio_ctl(vio=%p, cmd=%i, data=%p) = ?", vio, cmd, data);
171
172 if ( vio == NULL ) {
173  roar_err_set(ROAR_ERROR_FAULT);
174  return -1;
175 }
176
177 ROAR_DBG("roar_vio_ctl(vio=%p, cmd=0x%.8x, data=%p): vio->ctl=%p", vio, cmd, data, vio->ctl);
178
179 switch (cmd) {
180  case ROAR_VIO_CTL_CONFLICTING_ID_0:
181  case ROAR_VIO_CTL_CONFLICTING_ID_1:
182    ROAR_ERR("roar_vio_ctl(vio=%p, cmd=0x%.8x, data=%p): Your progam uses a VIO ctl call with a conflicting ID.", vio, cmd, data);
183    ROAR_ERR("roar_vio_ctl(vio=%p, cmd=0x%.8x, data=%p): Please recompile your program to fix this. (No additional steps are required beside that.)", vio, cmd, data);
184    ROAR_DBG("roar_vio_ctl(vio=%p, cmd=0x%.8x, data=%p) = -1", vio, cmd, data);
185    roar_err_set(ROAR_ERROR_BADRQC);
186    return -1;
187   break;
188 }
189
190 if ( vio->ctl == NULL ) {
191  roar_err_set(ROAR_ERROR_NOSYS);
192  return -1;
193 }
194
195 roar_err_clear_all();
196 ret = vio->ctl(vio, cmd, data);
197 roar_err_update();
198
199 return ret;
200}
201
202int     roar_vio_close    (struct roar_vio_calls * vio) {
203 int ret;
204
205 ROAR_DBG("roar_vio_close(vio=%p) = ?", vio);
206
207 if ( vio == NULL ) {
208  roar_err_set(ROAR_ERROR_FAULT);
209  return -1;
210 }
211
212 if ( vio->close == NULL ) {
213  roar_err_set(ROAR_ERROR_NOSYS);
214  return -1;
215 }
216
217 roar_err_clear_all();
218 ret = vio->close(vio);
219 roar_err_update();
220
221 return ret;
222}
223
224// specal commands:
225int     roar_vio_accept  (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
226 if (dst == NULL || calls == NULL) {
227  roar_err_set(ROAR_ERROR_FAULT);
228  return -1;
229 }
230
231 return roar_vio_ctl(dst, ROAR_VIO_CTL_ACCEPT, calls);
232}
233
234int     roar_vio_shutdown(struct roar_vio_calls * vio,   int how) {
235 if (vio == NULL) {
236  roar_err_set(ROAR_ERROR_FAULT);
237  return -1;
238 }
239
240 if ( ( (how | ROAR_VIO_SHUTDOWN_READ|ROAR_VIO_SHUTDOWN_WRITE|ROAR_VIO_SHUTDOWN_LISTEN) -
241        (ROAR_VIO_SHUTDOWN_READ|ROAR_VIO_SHUTDOWN_WRITE|ROAR_VIO_SHUTDOWN_LISTEN) ) != 0 ) {
242  roar_err_set(ROAR_ERROR_INVAL);
243  return -1;
244 }
245
246 return roar_vio_ctl(vio, ROAR_VIO_CTL_SHUTDOWN, &how);
247}
248
249// converters:
250int     roar_vio_open_fh       (struct roar_vio_calls * calls, int fh) {
251 if ( calls == NULL ) {
252  roar_err_set(ROAR_ERROR_FAULT);
253  return -1;
254 }
255
256 memset((void*)calls, 0, sizeof(struct roar_vio_calls));
257
258 calls->read     = roar_vio_basic_read;
259 calls->write    = roar_vio_basic_write;
260 calls->lseek    = roar_vio_basic_lseek;
261 calls->sync     = roar_vio_basic_sync;
262 calls->ctl      = roar_vio_basic_ctl;
263 calls->close    = roar_vio_basic_close;
264
265 calls->inst     = (void*)(ROAR_INSTINT)(fh + 1);
266
267 return 0;
268}
269
270int     roar_vio_open_fh_socket(struct roar_vio_calls * calls, int fh) {
271 if ( calls == NULL ) {
272  roar_err_set(ROAR_ERROR_FAULT);
273  return -1;
274 }
275
276 if ( roar_vio_open_fh(calls, fh) == -1 )
277  return -1;
278
279#ifdef ROAR_TARGET_WIN32
280 calls->read     = roar_vio_winsock_read;
281 calls->write    = roar_vio_winsock_write;
282 calls->sync     = roar_vio_winsock_sync;
283 calls->ctl      = roar_vio_winsock_ctl;
284 calls->close    = roar_vio_winsock_close;
285#else
286 calls->sync     = roar_vio_null_sync;
287#endif
288
289 return 0;
290}
291
292int     roar_vio_open_socket   (struct roar_vio_calls * calls, const char * host, int port) {
293 int fh;
294
295 if ( calls == NULL ) {
296  roar_err_set(ROAR_ERROR_FAULT);
297  return -1;
298 }
299
300 if ( (fh = roar_socket_connect(ROAR_SOCKET_TYPE_UNKNOWN, host, port)) == -1 )
301  return -1;
302
303 return roar_vio_open_fh_socket(calls, fh);
304}
305
306int     roar_vio_open_socket_listen(struct roar_vio_calls * calls, int type, const char * host, int port) {
307 int fh;
308
309 if ( calls == NULL ) {
310  roar_err_set(ROAR_ERROR_FAULT);
311  return -1;
312 }
313
314 if ( (fh = roar_socket_listen(type, host, port)) == -1 )
315  return -1;
316
317 return roar_vio_open_fh_socket(calls, fh);
318}
319
320
321// VIOs:
322
323// basic
324ssize_t roar_vio_basic_read (struct roar_vio_calls * vio, void *buf, size_t count) {
325#ifdef _CAN_OPERATE
326 return read(roar_vio_get_fh(vio), buf, count);
327#else
328 roar_err_set(ROAR_ERROR_NOSYS);
329 return -1;
330#endif
331}
332
333ssize_t roar_vio_basic_write(struct roar_vio_calls * vio, void *buf, size_t count) {
334#ifdef _CAN_OPERATE
335 return write(roar_vio_get_fh(vio), buf, count);
336#else
337 roar_err_set(ROAR_ERROR_NOSYS);
338 return -1;
339#endif
340}
341
342roar_off_t   roar_vio_basic_lseek(struct roar_vio_calls * vio, roar_off_t offset, int whence) {
343#ifdef _CAN_OPERATE
344 return lseek(roar_vio_get_fh(vio), offset, whence);
345#else
346 roar_err_set(ROAR_ERROR_NOSYS);
347 return -1;
348#endif
349}
350
351int     roar_vio_basic_sync    (struct roar_vio_calls * vio) {
352#ifdef ROAR_FDATASYNC
353 return ROAR_FDATASYNC(roar_vio_get_fh(vio));
354#else
355 return 0;
356#endif
357}
358
359int     roar_vio_basic_ctl     (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
360#ifdef ROAR_HAVE_H_SYS_IOCTL
361 struct roar_vio_sysio_ioctl * sysioctl;
362#endif
363#if defined(ROAR_HAVE_GETSOCKOPT) || defined(ROAR_HAVE_SETSOCKOPT)
364 struct roar_vio_sysio_sockopt  * syssockopt;
365#endif
366 int tmp;
367 int s_r = 0, s_w = 0;
368#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
369 union {
370  struct sockaddr     sa;
371#if defined(ROAR_HAVE_IPV4) || defined(ROAR_HAVE_IPV6)
372  struct sockaddr_in  in;
373#endif
374#ifdef ROAR_HAVE_UNIX
375  struct sockaddr_un  un;
376#endif
377#ifdef ROAR_HAVE_LIBDNET
378  struct sockaddr_dn  dn;
379#endif
380#ifdef ROAR_HAVE_IPV6
381  struct sockaddr_in6 in6;
382#endif
383#ifdef ROAR_HAVE_IPX
384  struct sockaddr_ipx ipx;
385#endif
386 } sockaddr;
387 socklen_t socklen;
388 struct roar_sockname * rsockname;
389#endif
390
391 if ( vio == NULL ) {
392  roar_err_set(ROAR_ERROR_FAULT);
393  return -1;
394 }
395
396 if ( cmd == -1 ) {
397  roar_err_set(ROAR_ERROR_INVAL);
398  return -1;
399 }
400
401 ROAR_DBG("roar_vio_basic_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data);
402
403 switch (cmd) {
404  case ROAR_VIO_CTL_GET_NAME:
405    if ( data == NULL ) {
406     roar_err_set(ROAR_ERROR_FAULT);
407     return -1;
408    }
409
410    *(char**)data = "basic";
411    return 0;
412   break;
413  case ROAR_VIO_CTL_GET_FH:
414  case ROAR_VIO_CTL_GET_READ_FH:
415  case ROAR_VIO_CTL_GET_WRITE_FH:
416  case ROAR_VIO_CTL_GET_SELECT_FH:
417  case ROAR_VIO_CTL_GET_SELECT_READ_FH:
418  case ROAR_VIO_CTL_GET_SELECT_WRITE_FH:
419    ROAR_DBG("roar_vio_basic_ctl(vio=%p, cmd=ROAR_VIO_CTL_GET_*FH(0x%.8x), data=%p) = 0 // fh=%i", vio, cmd, data, roar_vio_get_fh(vio));
420    *(int*)data = roar_vio_get_fh(vio);
421    return 0;
422   break;
423  case ROAR_VIO_CTL_SET_NOSYNC:
424    vio->sync = NULL;
425    return 0;
426   break;
427  case ROAR_VIO_CTL_ACCEPT:
428    tmp = ROAR_ACCEPT(roar_vio_get_fh(vio), NULL, 0);
429    if ( tmp == -1 )
430     return -1;
431
432    // most proably a socket.
433    if ( roar_vio_open_fh_socket(data, tmp) == -1 ) {
434#ifdef ROAR_TARGET_WIN32
435     closesocket(tmp);
436#else
437     close(tmp);
438#endif
439     return -1;
440    }
441
442    return 0;
443   break;
444  case ROAR_VIO_CTL_SHUTDOWN:
445    tmp = *(int*)data;
446
447    if ( tmp & ROAR_VIO_SHUTDOWN_READ ) {
448     s_r = 1;
449     tmp -= ROAR_VIO_SHUTDOWN_READ;
450    }
451
452    if ( tmp & ROAR_VIO_SHUTDOWN_WRITE ) {
453     s_w = 1;
454     tmp -= ROAR_VIO_SHUTDOWN_WRITE;
455    }
456
457    if ( tmp != 0 ) { /* we currently only support R and W shutdowns */
458     roar_err_set(ROAR_ERROR_NOTSUP);
459     return -1;
460    }
461
462    if ( s_r && s_w ) {
463     tmp = SHUT_RDWR;
464    } else if ( s_r ) {
465     tmp = SHUT_RD;
466    } else if ( s_w ) {
467     tmp = SHUT_WR;
468    } else {
469     return 0; // nothing to do.
470    }
471
472    return ROAR_SHUTDOWN(roar_vio_get_fh(vio), tmp);
473   break;
474#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
475  case ROAR_VIO_CTL_GET_SOCKNAME:
476  case ROAR_VIO_CTL_GET_PEERNAME:
477    if ( data == NULL ) {
478     roar_err_set(ROAR_ERROR_FAULT);
479     return -1;
480    }
481
482    rsockname = data;
483
484    socklen = sizeof(sockaddr);
485
486    if ( cmd == ROAR_VIO_CTL_GET_SOCKNAME ) {
487#ifdef ROAR_HAVE_GETSOCKNAME
488     tmp = getsockname(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
489#else
490     roar_err_set(ROAR_ERROR_NOSYS);
491     return -1;
492#endif
493    } else if ( cmd == ROAR_VIO_CTL_GET_PEERNAME ) {
494#ifdef ROAR_HAVE_GETPEERNAME
495     tmp = getpeername(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
496#else
497     roar_err_set(ROAR_ERROR_NOSYS);
498     return -1;
499#endif
500    } else {
501     // memory corruption:
502     roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
503     roar_err_set(ROAR_ERROR_CHERNOBYL);
504     return -1;
505    }
506
507    if ( tmp == -1 )
508     return -1;
509
510    memset(rsockname, 0, sizeof(struct roar_sockname));
511
512    switch (sockaddr.sa.sa_family) {
513#if defined(AF_UNIX) && defined(ROAR_HAVE_UNIX)
514     case AF_UNIX:
515       rsockname->type = ROAR_SOCKET_TYPE_UNIX;
516       if ( sockaddr.un.sun_path[0] == 0 ) {
517        rsockname->addr = roar_mm_malloc(sizeof(sockaddr.un.sun_path));
518        if ( rsockname->addr == NULL )
519         return -1;
520        memcpy(rsockname->addr, sockaddr.un.sun_path, sizeof(sockaddr.un.sun_path));
521       } else {
522        rsockname->addr = roar_mm_strdup(sockaddr.un.sun_path);
523       }
524      break;
525#endif
526#if defined(AF_DECnet) && defined(ROAR_HAVE_LIBDNET)
527     case AF_DECnet:
528       rsockname->type = ROAR_SOCKET_TYPE_DECNET;
529
530       if ( sockaddr.dn.sdn_add.a_len != 2 ) {
531        roar_err_set(ROAR_ERROR_NOTSUP);
532        return -1;
533       }
534
535       rsockname->addr = roar_mm_malloc(28);
536       if ( rsockname->addr == NULL )
537        return -1;
538
539       snprintf(rsockname->addr, 28, "%i.%i::",
540                 sockaddr.dn.sdn_add.a_addr[1] >> 2,
541                 sockaddr.dn.sdn_add.a_addr[0] + ((sockaddr.dn.sdn_add.a_addr[1] & 0x03) << 8));
542
543       rsockname->port = sockaddr.dn.sdn_objnum;
544       if ( sockaddr.dn.sdn_objnum == 0 ) {
545        tmp = strlen(rsockname->addr);
546        memcpy(rsockname->addr + tmp, sockaddr.dn.sdn_objname, sockaddr.dn.sdn_objnamel);
547        rsockname->addr[tmp + sockaddr.dn.sdn_objnamel] = 0;
548       }
549      break;
550#endif
551#if defined(AF_INET) && (defined(ROAR_HAVE_IPV4) || defined(ROAR_HAVE_IPV6))
552     case AF_INET:
553       rsockname->type = ROAR_SOCKET_TYPE_INET;
554       rsockname->port = ntohs(sockaddr.in.sin_port);
555       rsockname->addr = roar_mm_strdup(inet_ntoa(sockaddr.in.sin_addr));
556      break;
557#endif
558#if defined(AF_INET6) && defined(ROAR_HAVE_IPV6)
559     case AF_INET6:
560       rsockname->type = ROAR_SOCKET_TYPE_INET6;
561       rsockname->port = ntohs(sockaddr.in6.sin6_port);
562      break;
563#endif
564     default:
565       roar_err_set(ROAR_ERROR_NOTSUP);
566       return -1;
567    }
568    return 0;
569#endif
570   break;
571#ifdef ROAR_HAVE_H_SYS_IOCTL
572  case ROAR_VIO_CTL_SYSIO_IOCTL:
573    sysioctl = data;
574    return ioctl(roar_vio_get_fh(vio), sysioctl->cmd, sysioctl->argp);
575   break;
576#endif
577#ifdef ROAR_HAVE_GETSOCKOPT
578  case ROAR_VIO_CTL_GET_SYSIO_SOCKOPT:
579    syssockopt = data;
580    return getsockopt(roar_vio_get_fh(vio), syssockopt->level, syssockopt->optname, syssockopt->optval, &(syssockopt->optlen));
581   break;
582#endif
583#ifdef ROAR_HAVE_SETSOCKOPT
584  case ROAR_VIO_CTL_SET_SYSIO_SOCKOPT:
585    syssockopt = data;
586    return setsockopt(roar_vio_get_fh(vio), syssockopt->level, syssockopt->optname, syssockopt->optval, syssockopt->optlen);
587   break;
588#endif
589  case ROAR_VIO_CTL_NONBLOCK:
590    if ( roar_socket_nonblock(roar_vio_get_fh(vio), *(int*)data) == -1 )
591     return -1;
592
593    if ( *(int*)data == ROAR_SOCKET_NONBLOCK )
594     return 0;
595
596    roar_vio_sync(vio);
597    return 0;
598   break;
599 }
600
601 roar_err_set(ROAR_ERROR_BADRQC);
602 return -1;
603}
604
605int     roar_vio_basic_close    (struct roar_vio_calls * vio) {
606#ifdef _CAN_OPERATE
607 if ( roar_vio_get_fh(vio) != -1 )
608  return close(roar_vio_get_fh(vio));
609
610 return 0;
611#else
612 roar_err_set(ROAR_ERROR_NOSYS);
613 return -1;
614#endif
615}
616
617// null
618ssize_t roar_vio_null_rw    (struct roar_vio_calls * vio, void *buf, size_t count) {
619 (void)count;
620
621 if ( vio == NULL || buf == NULL ) {
622  roar_err_set(ROAR_ERROR_FAULT);
623  return -1;
624 }
625
626 return 0;
627}
628
629int     roar_vio_null_sync    (struct roar_vio_calls * vio) {
630 (void)vio;
631 return 0;
632}
633
634// pass
635int     roar_vio_open_pass    (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
636 if ( calls == NULL || dst == NULL ) {
637  roar_err_set(ROAR_ERROR_FAULT);
638  return -1;
639 }
640
641 memset((void*)calls, 0, sizeof(struct roar_vio_calls));
642
643 calls->read     = roar_vio_pass_read;
644 calls->write    = roar_vio_pass_write;
645 calls->lseek    = roar_vio_pass_lseek;
646 calls->sync     = roar_vio_pass_sync;
647 calls->ctl      = roar_vio_pass_ctl;
648 calls->close    = roar_vio_pass_close;
649
650 calls->inst     = dst;
651
652 return 0;
653}
654
655ssize_t roar_vio_pass_read (struct roar_vio_calls * vio, void *buf, size_t count) {
656 return roar_vio_read((struct roar_vio_calls *) vio->inst, buf, count);
657}
658
659ssize_t roar_vio_pass_write(struct roar_vio_calls * vio, void *buf, size_t count) {
660 return roar_vio_write((struct roar_vio_calls *) vio->inst, buf, count);
661}
662
663roar_off_t   roar_vio_pass_lseek(struct roar_vio_calls * vio, roar_off_t offset, int whence) {
664 return roar_vio_lseek((struct roar_vio_calls *) vio->inst, offset, whence);
665}
666
667int     roar_vio_pass_sync    (struct roar_vio_calls * vio) {
668 return roar_vio_sync((struct roar_vio_calls *) vio->inst);
669}
670
671int     roar_vio_pass_ctl     (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
672 if (vio == NULL) {
673  roar_err_set(ROAR_ERROR_FAULT);
674  return -1;
675 }
676
677 if (cmd == -1) {
678  roar_err_set(ROAR_ERROR_INVAL);
679  return -1;
680 }
681
682 ROAR_DBG("roar_vio_pass_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data);
683
684 switch (cmd) {
685  case ROAR_VIO_CTL_GET_NAME:
686    if ( data == NULL ) {
687     roar_err_set(ROAR_ERROR_FAULT);
688     return -1;
689    }
690
691    // dirty trick to get real name...
692    if ( vio->read == roar_vio_re_read ) {
693     *(char**)data = "re";
694    } else {
695     *(char**)data = "pass";
696    }
697    return 0;
698   break;
699  case ROAR_VIO_CTL_GET_NEXT:
700    *(struct roar_vio_calls **)data = vio->inst;
701    return 0;
702   break;
703  case ROAR_VIO_CTL_SET_NEXT:
704    vio->inst = *(struct roar_vio_calls **)data;
705    return 0;
706   break;
707 }
708
709 return roar_vio_ctl((struct roar_vio_calls *) vio->inst, cmd, data);
710}
711
712int     roar_vio_pass_close   (struct roar_vio_calls * vio) {
713 return roar_vio_close((struct roar_vio_calls *) vio->inst);
714}
715
716
717// re
718int     roar_vio_open_re (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
719 if ( roar_vio_open_pass(calls, dst) == -1 )
720  return -1;
721
722 calls->read  = roar_vio_re_read;
723 calls->write = roar_vio_re_write;
724 calls->lseek = roar_vio_re_lseek;
725
726 return 0;
727}
728ssize_t roar_vio_re_read (struct roar_vio_calls * vio, void *buf, size_t count) {
729  size_t len =  0;
730 ssize_t r   = -1;
731
732 if ( vio == NULL ) {
733  roar_err_set(ROAR_ERROR_FAULT);
734  return -1;
735 }
736
737 if ( vio->inst == NULL ) {
738  roar_err_set(ROAR_ERROR_FAULT);
739  return -1;
740 }
741
742 roar_err_clear_all();
743
744 while ( (r = roar_vio_read((struct roar_vio_calls *) vio->inst, buf, count)) > 0 ) {
745  len   += r;
746  buf   += r;
747  count -= r;
748  if ( count == 0 )
749   break;
750 }
751
752 if ( len == 0 && r == -1 )
753  return -1;
754
755 return len;
756}
757
758ssize_t roar_vio_re_write(struct roar_vio_calls * vio, void *buf, size_t count) {
759  size_t len =  0;
760 ssize_t r   = -1;
761
762 if ( vio == NULL ) {
763  roar_err_set(ROAR_ERROR_FAULT);
764  return -1;
765 }
766
767 if ( vio->inst == NULL ) {
768  roar_err_set(ROAR_ERROR_FAULT);
769  return -1;
770 }
771
772 roar_err_clear_all();
773
774 while ( (r = roar_vio_write((struct roar_vio_calls *) vio->inst, buf, count)) > 0 ) {
775  len   += r;
776  buf   += r;
777  count -= r;
778  if ( count == 0 )
779   break;
780 }
781
782 if ( len == 0 && r == -1 )
783  return -1;
784
785 return len;
786}
787
788// TODO: we should do a some more intelgent thing here.
789roar_off_t   roar_vio_re_lseek(struct roar_vio_calls * vio, roar_off_t offset, int whence) {
790 return roar_vio_lseek((struct roar_vio_calls *) vio->inst, offset, whence);
791}
792
793//ll
Note: See TracBrowser for help on using the repository browser.