source: roaraudio/libroar/vio.c @ 4876:06a2f29d0450

Last change on this file since 4876:06a2f29d0450 was 4876:06a2f29d0450, checked in by phi, 13 years ago

some updates to handle error values better with DSTR

File size: 20.2 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#include "libroar.h"
37
38#ifdef ROAR_HAVE_H_SYS_IOCTL
39#include <sys/ioctl.h>
40#endif
41
42#ifdef ROAR_HAVE_IO_POSIX
43#define _CAN_OPERATE
44#endif
45
46int roar_vio_init_calls (struct roar_vio_calls * calls) {
47#ifdef _CAN_OPERATE
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/*
56 calls->read  = (ssize_t (*)(int fd, void *buf, size_t count,      void * inst))read;
57 calls->write = (ssize_t (*)(int fd, void *buf, size_t count,      void * inst))write;
58 calls->lseek = (off_t   (*)(int fildes, off_t offset, int whence, void * inst))lseek;
59*/
60
61 calls->read     = roar_vio_basic_read;
62 calls->write    = roar_vio_basic_write;
63 calls->lseek    = roar_vio_basic_lseek;
64 calls->nonblock = roar_vio_basic_nonblock;
65 calls->sync     = roar_vio_basic_sync;
66 calls->ctl      = roar_vio_basic_ctl;
67 calls->close    = roar_vio_basic_close;
68
69 return 0;
70#else
71 return -1;
72#endif
73}
74
75int roar_vio_set_inst (struct roar_vio_calls * vio, void * inst) {
76 if ( vio == NULL ) {
77  roar_err_set(ROAR_ERROR_FAULT);
78  return -1;
79 }
80
81 vio->inst = inst;
82
83 return 0;
84}
85
86int roar_vio_set_fh   (struct roar_vio_calls * vio, int fh) {
87 return roar_vio_set_inst(vio, (void*)(ROAR_INSTINT)(fh + 1));
88}
89
90int roar_vio_get_fh   (struct roar_vio_calls * vio) {
91 if ( vio == NULL ) {
92  roar_err_set(ROAR_ERROR_FAULT);
93  return -1;
94 }
95
96 return ((int)(ROAR_INSTINT)vio->inst) - 1;
97}
98
99
100ssize_t roar_vio_read (struct roar_vio_calls * vio, void *buf, size_t count) {
101 ssize_t ret;
102
103 ROAR_DBG("roar_vio_read(vio=%p, buf=%p, count=%u) = ?", vio, buf, (unsigned int)count);
104
105 if ( vio == NULL ) {
106  roar_err_set(ROAR_ERROR_FAULT);
107  return -1;
108 }
109
110 if ( vio->read == NULL ) {
111  roar_err_set(ROAR_ERROR_NOSYS);
112  return -1;
113 }
114
115 roar_err_clear_all();
116 ret = vio->read(vio, buf, count);
117 roar_err_update();
118
119 return ret;
120}
121
122ssize_t roar_vio_write(struct roar_vio_calls * vio, void *buf, size_t count) {
123 ssize_t ret;
124
125 ROAR_DBG("roar_vio_write(vio=%p, buf=%p, count=%u) = ?", vio, buf, (unsigned int)count);
126
127 if ( vio == NULL ) {
128  roar_err_set(ROAR_ERROR_FAULT);
129  return -1;
130 }
131
132 if ( vio->write == NULL ) {
133  roar_err_set(ROAR_ERROR_NOSYS);
134  return -1;
135 }
136
137 roar_err_clear_all();
138 ret = vio->write(vio, buf, count);
139 roar_err_update();
140
141 return ret;
142}
143
144off_t   roar_vio_lseek(struct roar_vio_calls * vio, off_t offset, int whence) {
145 off_t ret;
146
147 ROAR_DBG("roar_vio_lseek(vio=%p, offset=%u, whence=%i) = ?", vio, (unsigned int)offset, whence);
148
149 if ( vio == NULL ) {
150  roar_err_set(ROAR_ERROR_FAULT);
151  return -1;
152 }
153
154 if ( vio->lseek == NULL ) {
155  roar_err_set(ROAR_ERROR_NOSYS);
156  return -1;
157 }
158
159 roar_err_clear_all();
160 ret = vio->lseek(vio, offset, whence);
161 roar_err_update();
162
163 return ret;
164}
165
166int     roar_vio_nonblock(struct roar_vio_calls * vio, int state) {
167 int ret;
168
169 ROAR_DBG("roar_vio_nonblock(vio=%p, state=%i) = ?", vio, state);
170
171 if ( vio == NULL ) {
172  roar_err_set(ROAR_ERROR_FAULT);
173  return -1;
174 }
175
176 if ( vio->nonblock == NULL ) {
177  roar_err_set(ROAR_ERROR_NOSYS);
178  return -1;
179 }
180
181 roar_err_clear_all();
182 ret = vio->nonblock(vio, state);
183 roar_err_update();
184
185 return ret;
186}
187
188int     roar_vio_sync    (struct roar_vio_calls * vio) {
189 int ret;
190
191 ROAR_DBG("roar_vio_sync(vio=%p) = ?", vio);
192
193 if ( vio == NULL ) {
194  roar_err_set(ROAR_ERROR_FAULT);
195  return -1;
196 }
197
198 if ( vio->sync == NULL ) {
199  roar_err_set(ROAR_ERROR_NOSYS);
200  return -1;
201 }
202
203 roar_err_clear_all();
204 ret = vio->sync(vio);
205 roar_err_update();
206
207 return ret;
208}
209
210int     roar_vio_ctl     (struct roar_vio_calls * vio, int cmd, void * data) {
211 int ret;
212
213 ROAR_DBG("roar_vio_ctl(vio=%p, cmd=%i, data=%p) = ?", vio, cmd, data);
214
215 if ( vio == NULL ) {
216  roar_err_set(ROAR_ERROR_FAULT);
217  return -1;
218 }
219
220 ROAR_DBG("roar_vio_ctl(vio=%p, cmd=0x%.8x, data=%p): vio->ctl=%p", vio, cmd, data, vio->ctl);
221
222 switch (cmd) {
223  case ROAR_VIO_CTL_CONFLICTING_ID_0:
224  case ROAR_VIO_CTL_CONFLICTING_ID_1:
225    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);
226    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);
227    ROAR_DBG("roar_vio_ctl(vio=%p, cmd=0x%.8x, data=%p) = -1", vio, cmd, data);
228    roar_err_set(ROAR_ERROR_BADRQC);
229    return -1;
230   break;
231 }
232
233 if ( vio->ctl == NULL ) {
234  roar_err_set(ROAR_ERROR_NOSYS);
235  return -1;
236 }
237
238 roar_err_clear_all();
239 ret = vio->ctl(vio, cmd, data);
240 roar_err_update();
241
242 return ret;
243}
244
245int     roar_vio_close    (struct roar_vio_calls * vio) {
246 int ret;
247
248 ROAR_DBG("roar_vio_close(vio=%p) = ?", vio);
249
250 if ( vio == NULL ) {
251  roar_err_set(ROAR_ERROR_FAULT);
252  return -1;
253 }
254
255 if ( vio->close == NULL ) {
256  roar_err_set(ROAR_ERROR_NOSYS);
257  return -1;
258 }
259
260 roar_err_clear_all();
261 ret = vio->close(vio);
262 roar_err_update();
263
264 return ret;
265}
266
267// specal commands:
268int     roar_vio_accept  (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
269 if (dst == NULL || calls == NULL) {
270  roar_err_set(ROAR_ERROR_FAULT);
271  return -1;
272 }
273
274 return roar_vio_ctl(dst, ROAR_VIO_CTL_ACCEPT, calls);
275}
276
277int     roar_vio_shutdown(struct roar_vio_calls * vio,   int how) {
278 return roar_vio_ctl(vio, ROAR_VIO_CTL_SHUTDOWN, &how);
279}
280
281// converters:
282int     roar_vio_open_file     (struct roar_vio_calls * calls, char * filename, int flags, mode_t mode) {
283#ifdef _CAN_OPERATE
284 int fh;
285
286 roar_debug_warn_obsolete("roar_vio_open_file", "roar_vio_open_dstr", NULL);
287
288 if ( calls == NULL || filename == NULL ) {
289  roar_err_set(ROAR_ERROR_FAULT);
290  return -1;
291 }
292
293#ifdef ROAR_TARGET_WIN32
294 flags |= O_BINARY;
295#endif
296
297 roar_err_clear_all();
298 if ( (fh = open(filename, flags, mode)) == -1 ) {
299  ROAR_DBG("roar_vio_open_file(*): errno=%s", strerror(errno));
300  roar_err_update();
301  ROAR_DBG("roar_vio_open_file(*): errno=%s", strerror(errno));
302  return -1;
303 }
304
305 if ( roar_vio_open_fh(calls, fh) == -1 ) {
306  close(fh);
307  roar_err_update();
308  return -1;
309 }
310
311 roar_err_update();
312 return 0;
313#else
314 return -1;
315#endif
316}
317
318int     roar_vio_open_fh       (struct roar_vio_calls * calls, int fh) {
319 if ( calls == NULL )
320  return -1;
321
322 if ( roar_vio_init_calls(calls) == -1 )
323  return -1;
324
325 return roar_vio_set_fh(calls, fh);
326}
327
328int     roar_vio_open_fh_socket(struct roar_vio_calls * calls, int fh) {
329 if ( calls == NULL )
330  return -1;
331
332 if ( roar_vio_open_fh(calls, fh) == -1 )
333  return -1;
334
335#ifdef ROAR_TARGET_WIN32
336 calls->read     = roar_vio_winsock_read;
337 calls->write    = roar_vio_winsock_write;
338 calls->nonblock = roar_vio_winsock_nonblock;
339 calls->sync     = roar_vio_winsock_sync;
340 calls->ctl      = roar_vio_winsock_ctl;
341 calls->close    = roar_vio_winsock_close;
342#else
343 calls->sync     = roar_vio_null_sync;
344#endif
345
346 return 0;
347}
348
349int     roar_vio_open_socket   (struct roar_vio_calls * calls, char * host, int port) {
350 int fh;
351
352 if ( calls == NULL )
353  return -1;
354
355 if ( (fh = roar_socket_connect(host, port)) == -1 )
356  return -1;
357
358 return roar_vio_open_fh_socket(calls, fh);
359}
360
361int     roar_vio_open_socket_listen(struct roar_vio_calls * calls, int type, char * host, int port) {
362 int fh;
363
364 if ( calls == NULL )
365  return -1;
366
367 if ( (fh = roar_socket_listen(type, host, port)) == -1 )
368  return -1;
369
370 return roar_vio_open_fh_socket(calls, fh);
371}
372
373int     roar_vio_simple_stream (struct roar_vio_calls * calls, int rate, int channels, int bits, int codec,
374                                                               char * server, int dir, char * name) {
375 int fh;
376
377 if ( calls == NULL )
378  return -1;
379
380 roar_libroar_nowarn();
381 if ( (fh = roar_simple_stream(rate, channels, bits, codec, server, dir, name)) == -1 ) {
382  roar_libroar_warn();
383  return -1;
384 }
385 roar_libroar_warn();
386
387 return roar_vio_open_fh_socket(calls, fh);
388}
389
390int     roar_vio_simple_new_stream_obj (struct roar_vio_calls * calls,
391                                        struct roar_connection * con,
392                                        struct roar_stream * s,
393                                        int rate, int channels, int bits, int codec, int dir) {
394 struct roar_stream stream;
395 int fh;
396
397 ROAR_DBG("roar_vio_simple_new_stream_obj(*) = ?");
398
399 if ( calls == NULL )
400  return -1;
401
402 if ( s == NULL )
403  s = &stream;
404
405 roar_libroar_nowarn();
406 if ( (fh = roar_simple_new_stream_obj(con, s, rate, channels, bits, codec, dir)) == -1 ) {
407  roar_libroar_warn();
408  ROAR_DBG("roar_vio_simple_new_stream_obj(*) = -1");
409  return -1;
410 }
411 roar_libroar_warn();
412
413 ROAR_DBG("roar_vio_simple_new_stream_obj(*): fh=%i", fh);
414
415 return roar_vio_open_fh_socket(calls, fh);
416}
417
418// VIOs:
419
420// basic
421ssize_t roar_vio_basic_read (struct roar_vio_calls * vio, void *buf, size_t count) {
422#ifdef _CAN_OPERATE
423 return read(roar_vio_get_fh(vio), buf, count);
424#else
425 return -1;
426#endif
427}
428
429ssize_t roar_vio_basic_write(struct roar_vio_calls * vio, void *buf, size_t count) {
430#ifdef _CAN_OPERATE
431 return write(roar_vio_get_fh(vio), buf, count);
432#else
433 return -1;
434#endif
435}
436
437off_t   roar_vio_basic_lseek(struct roar_vio_calls * vio, off_t offset, int whence) {
438#ifdef _CAN_OPERATE
439 return lseek(roar_vio_get_fh(vio), offset, whence);
440#else
441 return -1;
442#endif
443}
444
445int     roar_vio_basic_nonblock(struct roar_vio_calls * vio, int state) {
446 if ( roar_socket_nonblock(roar_vio_get_fh(vio), state) == -1 )
447  return -1;
448
449 if ( state == ROAR_SOCKET_NONBLOCK )
450  return 0;
451
452 roar_vio_sync(vio);
453
454 return 0;
455}
456
457int     roar_vio_basic_sync    (struct roar_vio_calls * vio) {
458#ifdef ROAR_FDATASYNC
459 return ROAR_FDATASYNC(roar_vio_get_fh(vio));
460#else
461 return 0;
462#endif
463}
464
465int     roar_vio_basic_ctl     (struct roar_vio_calls * vio, int cmd, void * data) {
466#ifdef ROAR_HAVE_H_SYS_IOCTL
467 struct roar_vio_sysio_ioctl * sysioctl;
468#endif
469#if defined(ROAR_HAVE_GETSOCKOPT) || defined(ROAR_HAVE_SETSOCKOPT)
470 struct roar_vio_sysio_sockopt  * syssockopt;
471#endif
472 int tmp;
473 int s_r = 0, s_w = 0;
474#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
475 union {
476  struct sockaddr     sa;
477#if defined(ROAR_HAVE_IPV4) || defined(ROAR_HAVE_IPV6)
478  struct sockaddr_in  in;
479#endif
480#ifdef ROAR_HAVE_UNIX
481  struct sockaddr_un  un;
482#endif
483#ifdef ROAR_HAVE_LIBDNET
484  struct sockaddr_dn  dn;
485#endif
486#ifdef ROAR_HAVE_IPV6
487  struct sockaddr_in6 in6;
488#endif
489#ifdef ROAR_HAVE_IPX
490  struct sockaddr_ipx ipx;
491#endif
492 } sockaddr;
493 socklen_t socklen;
494 struct roar_sockname * rsockname;
495#endif
496
497 if ( vio == NULL || cmd == -1 )
498  return -1;
499
500 ROAR_DBG("roar_vio_basic_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data);
501
502 switch (cmd) {
503  case ROAR_VIO_CTL_GET_NAME:
504    if ( data == NULL )
505     return -1;
506
507    *(char**)data = "basic";
508    return 0;
509   break;
510  case ROAR_VIO_CTL_GET_FH:
511  case ROAR_VIO_CTL_GET_READ_FH:
512  case ROAR_VIO_CTL_GET_WRITE_FH:
513  case ROAR_VIO_CTL_GET_SELECT_FH:
514  case ROAR_VIO_CTL_GET_SELECT_READ_FH:
515  case ROAR_VIO_CTL_GET_SELECT_WRITE_FH:
516    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));
517    *(int*)data = roar_vio_get_fh(vio);
518    return 0;
519   break;
520  case ROAR_VIO_CTL_SET_NOSYNC:
521    vio->sync = NULL;
522    return 0;
523   break;
524  case ROAR_VIO_CTL_ACCEPT:
525    tmp = ROAR_ACCEPT(roar_vio_get_fh(vio), NULL, 0);
526    if ( tmp == -1 )
527     return -1;
528
529    // most proably a socket.
530    if ( roar_vio_open_fh_socket(data, tmp) == -1 ) {
531#ifdef ROAR_TARGET_WIN32
532     closesocket(tmp);
533#else
534     close(tmp);
535#endif
536     return -1;
537    }
538
539    return 0;
540   break;
541  case ROAR_VIO_CTL_SHUTDOWN:
542    tmp = *(int*)data;
543
544    if ( tmp & ROAR_VIO_SHUTDOWN_READ ) {
545     s_r = 1;
546     tmp -= ROAR_VIO_SHUTDOWN_READ;
547    }
548
549    if ( tmp & ROAR_VIO_SHUTDOWN_WRITE ) {
550     s_w = 1;
551     tmp -= ROAR_VIO_SHUTDOWN_WRITE;
552    }
553
554    if ( tmp != 0 ) /* we currently only support R and W shutdowns */
555     return -1;
556
557    if ( s_r && s_w ) {
558     tmp = SHUT_RDWR;
559    } else if ( s_r ) {
560     tmp = SHUT_RD;
561    } else if ( s_w ) {
562     tmp = SHUT_WR;
563    } else {
564     return 0; // nothing to do.
565    }
566
567    return ROAR_SHUTDOWN(roar_vio_get_fh(vio), tmp);
568   break;
569#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
570  case ROAR_VIO_CTL_GET_SOCKNAME:
571  case ROAR_VIO_CTL_GET_PEERNAME:
572    if ( data == NULL )
573     return -1;
574
575    rsockname = data;
576
577    socklen = sizeof(sockaddr);
578
579    if ( cmd == ROAR_VIO_CTL_GET_SOCKNAME ) {
580#ifdef ROAR_HAVE_GETSOCKNAME
581     tmp = getsockname(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
582#else
583     return -1;
584#endif
585    } else if ( cmd == ROAR_VIO_CTL_GET_PEERNAME ) {
586#ifdef ROAR_HAVE_GETPEERNAME
587     tmp = getpeername(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
588#else
589     return -1;
590#endif
591    } else {
592     return -1;
593    }
594
595    if ( tmp == -1 )
596     return -1;
597
598    memset(rsockname, 0, sizeof(struct roar_sockname));
599
600    switch (sockaddr.sa.sa_family) {
601#if defined(AF_UNIX) && defined(ROAR_HAVE_UNIX)
602     case AF_UNIX:
603       rsockname->type = ROAR_SOCKET_TYPE_UNIX;
604       if ( sockaddr.un.sun_path[0] == 0 ) {
605        rsockname->addr = roar_mm_malloc(sizeof(sockaddr.un.sun_path));
606        if ( rsockname->addr == NULL )
607         return -1;
608        memcpy(rsockname->addr, sockaddr.un.sun_path, sizeof(sockaddr.un.sun_path));
609       } else {
610        rsockname->addr = roar_mm_strdup(sockaddr.un.sun_path);
611       }
612      break;
613#endif
614#if defined(AF_DECnet) && defined(ROAR_HAVE_LIBDNET)
615     case AF_DECnet:
616       rsockname->type = ROAR_SOCKET_TYPE_DECNET;
617
618       if ( sockaddr.dn.sdn_add.a_len != 2 )
619        return -1;
620
621       rsockname->addr = roar_mm_malloc(28);
622       if ( rsockname->addr == NULL )
623        return -1;
624
625       snprintf(rsockname->addr, 28, "%i.%i::",
626                 sockaddr.dn.sdn_add.a_addr[1] >> 2,
627                 sockaddr.dn.sdn_add.a_addr[0] + ((sockaddr.dn.sdn_add.a_addr[1] & 0x03) << 8));
628
629       rsockname->port = sockaddr.dn.sdn_objnum;
630       if ( sockaddr.dn.sdn_objnum == 0 ) {
631        tmp = strlen(rsockname->addr);
632        memcpy(rsockname->addr + tmp, sockaddr.dn.sdn_objname, sockaddr.dn.sdn_objnamel);
633        rsockname->addr[tmp + sockaddr.dn.sdn_objnamel] = 0;
634       }
635      break;
636#endif
637#if defined(AF_INET) && (defined(ROAR_HAVE_IPV4) || defined(ROAR_HAVE_IPV6))
638     case AF_INET:
639       rsockname->type = ROAR_SOCKET_TYPE_INET;
640       rsockname->port = ntohs(sockaddr.in.sin_port);
641       rsockname->addr = roar_mm_strdup(inet_ntoa(sockaddr.in.sin_addr));
642      break;
643#endif
644#if defined(AF_INET6) && defined(ROAR_HAVE_IPV6)
645     case AF_INET6:
646       rsockname->type = ROAR_SOCKET_TYPE_INET6;
647       rsockname->port = ntohs(sockaddr.in6.sin6_port);
648      break;
649#endif
650     default:
651       return -1;
652    }
653    return 0;
654#endif
655   break;
656#ifdef ROAR_HAVE_H_SYS_IOCTL
657  case ROAR_VIO_CTL_SYSIO_IOCTL:
658    sysioctl = data;
659    return ioctl(roar_vio_get_fh(vio), sysioctl->cmd, sysioctl->argp);
660   break;
661#endif
662#ifdef ROAR_HAVE_GETSOCKOPT
663  case ROAR_VIO_CTL_GET_SYSIO_SOCKOPT:
664    syssockopt = data;
665    return getsockopt(roar_vio_get_fh(vio), syssockopt->level, syssockopt->optname, syssockopt->optval, &(syssockopt->optlen));
666   break;
667#endif
668#ifdef ROAR_HAVE_SETSOCKOPT
669  case ROAR_VIO_CTL_SET_SYSIO_SOCKOPT:
670    syssockopt = data;
671    return setsockopt(roar_vio_get_fh(vio), syssockopt->level, syssockopt->optname, syssockopt->optval, syssockopt->optlen);
672   break;
673#endif
674 }
675
676 roar_err_set(ROAR_ERROR_BADRQC);
677 return -1;
678}
679
680int     roar_vio_basic_close    (struct roar_vio_calls * vio) {
681#ifdef _CAN_OPERATE
682 if ( roar_vio_get_fh(vio) != -1 )
683  return close(roar_vio_get_fh(vio));
684
685 return 0;
686#else
687 return -1;
688#endif
689}
690
691// null
692ssize_t roar_vio_null_rw    (struct roar_vio_calls * vio, void *buf, size_t count) {
693 if ( vio == NULL || buf == NULL )
694  return -1;
695
696 return 0;
697}
698
699int     roar_vio_null_sync    (struct roar_vio_calls * vio) {
700 return 0;
701}
702
703// pass
704int     roar_vio_open_pass    (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
705 if ( calls == NULL )
706  return -1;
707
708 memset((void*)calls, 0, sizeof(struct roar_vio_calls));
709
710 calls->read     = roar_vio_pass_read;
711 calls->write    = roar_vio_pass_write;
712 calls->lseek    = roar_vio_pass_lseek;
713 calls->nonblock = roar_vio_pass_nonblock;
714 calls->sync     = roar_vio_pass_sync;
715 calls->ctl      = roar_vio_pass_ctl;
716 calls->close    = roar_vio_pass_close;
717
718 calls->inst     = dst;
719
720 return 0;
721}
722
723ssize_t roar_vio_pass_read (struct roar_vio_calls * vio, void *buf, size_t count) {
724 return roar_vio_read((struct roar_vio_calls *) vio->inst, buf, count);
725}
726
727ssize_t roar_vio_pass_write(struct roar_vio_calls * vio, void *buf, size_t count) {
728 return roar_vio_write((struct roar_vio_calls *) vio->inst, buf, count);
729}
730
731off_t   roar_vio_pass_lseek(struct roar_vio_calls * vio, off_t offset, int whence) {
732 return roar_vio_lseek((struct roar_vio_calls *) vio->inst, offset, whence);
733}
734
735int     roar_vio_pass_nonblock(struct roar_vio_calls * vio, int state) {
736 return roar_vio_nonblock((struct roar_vio_calls *) vio->inst, state);
737}
738
739int     roar_vio_pass_sync    (struct roar_vio_calls * vio) {
740 return roar_vio_sync((struct roar_vio_calls *) vio->inst);
741}
742
743int     roar_vio_pass_ctl     (struct roar_vio_calls * vio, int cmd, void * data) {
744 if (vio == NULL || cmd == -1)
745  return -1;
746
747 ROAR_DBG("roar_vio_pass_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data);
748
749 switch (cmd) {
750  case ROAR_VIO_CTL_GET_NAME:
751    if ( data == NULL )
752     return -1;
753
754    // dirty trick to get real name...
755    if ( vio->read == roar_vio_re_read ) {
756     *(char**)data = "re";
757    } else {
758     *(char**)data = "pass";
759    }
760    return 0;
761   break;
762  case ROAR_VIO_CTL_GET_NEXT:
763    *(struct roar_vio_calls **)data = vio->inst;
764    return 0;
765   break;
766  case ROAR_VIO_CTL_SET_NEXT:
767    vio->inst = *(struct roar_vio_calls **)data;
768    return 0;
769   break;
770 }
771
772 return roar_vio_ctl((struct roar_vio_calls *) vio->inst, cmd, data);
773}
774
775int     roar_vio_pass_close   (struct roar_vio_calls * vio) {
776 return roar_vio_close((struct roar_vio_calls *) vio->inst);
777}
778
779
780// re
781int     roar_vio_open_re (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
782 if ( roar_vio_open_pass(calls, dst) == -1 )
783  return -1;
784
785 calls->read  = roar_vio_re_read;
786 calls->write = roar_vio_re_write;
787 calls->lseek = roar_vio_re_lseek;
788
789 return 0;
790}
791ssize_t roar_vio_re_read (struct roar_vio_calls * vio, void *buf, size_t count) {
792  size_t len =  0;
793 ssize_t r   = -1;
794
795 if ( vio == NULL )
796  return -1;
797
798 if ( vio->inst == NULL )
799  return -1;
800
801 roar_err_clear_all();
802
803 while ( (r = roar_vio_read((struct roar_vio_calls *) vio->inst, buf, count)) > 0 ) {
804  len   += r;
805  buf   += r;
806  count -= r;
807  if ( count == 0 )
808   break;
809 }
810
811 if ( len == 0 && r == -1 )
812  return -1;
813
814 return len;
815}
816
817ssize_t roar_vio_re_write(struct roar_vio_calls * vio, void *buf, size_t count) {
818  size_t len =  0;
819 ssize_t r   = -1;
820
821 if ( vio == NULL )
822  return -1;
823
824 if ( vio->inst == NULL )
825  return -1;
826
827 roar_err_clear_all();
828
829 while ( (r = roar_vio_write((struct roar_vio_calls *) vio->inst, buf, count)) > 0 ) {
830  len   += r;
831  buf   += r;
832  count -= r;
833  if ( count == 0 )
834   break;
835 }
836
837 if ( len == 0 && r == -1 )
838  return -1;
839
840 return len;
841}
842
843// TODO: we should do a some more intelgent thing here.
844off_t   roar_vio_re_lseek(struct roar_vio_calls * vio, off_t offset, int whence) {
845 return roar_vio_lseek((struct roar_vio_calls *) vio->inst, offset, whence);
846}
847
848//ll
Note: See TracBrowser for help on using the repository browser.