source: roaraudio/libroar/vio.c @ 4873:98d17d4deeec

Last change on this file since 4873:98d17d4deeec was 4873:98d17d4deeec, checked in by phi, 13 years ago

make use of new error stuff

File size: 20.1 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_err_update();
300  return -1;
301 }
302
303 if ( roar_vio_open_fh(calls, fh) == -1 ) {
304  close(fh);
305  roar_err_update();
306  return -1;
307 }
308
309 roar_err_update();
310 return 0;
311#else
312 return -1;
313#endif
314}
315
316int     roar_vio_open_fh       (struct roar_vio_calls * calls, int fh) {
317 if ( calls == NULL )
318  return -1;
319
320 if ( roar_vio_init_calls(calls) == -1 )
321  return -1;
322
323 return roar_vio_set_fh(calls, fh);
324}
325
326int     roar_vio_open_fh_socket(struct roar_vio_calls * calls, int fh) {
327 if ( calls == NULL )
328  return -1;
329
330 if ( roar_vio_open_fh(calls, fh) == -1 )
331  return -1;
332
333#ifdef ROAR_TARGET_WIN32
334 calls->read     = roar_vio_winsock_read;
335 calls->write    = roar_vio_winsock_write;
336 calls->nonblock = roar_vio_winsock_nonblock;
337 calls->sync     = roar_vio_winsock_sync;
338 calls->ctl      = roar_vio_winsock_ctl;
339 calls->close    = roar_vio_winsock_close;
340#else
341 calls->sync     = roar_vio_null_sync;
342#endif
343
344 return 0;
345}
346
347int     roar_vio_open_socket   (struct roar_vio_calls * calls, char * host, int port) {
348 int fh;
349
350 if ( calls == NULL )
351  return -1;
352
353 if ( (fh = roar_socket_connect(host, port)) == -1 )
354  return -1;
355
356 return roar_vio_open_fh_socket(calls, fh);
357}
358
359int     roar_vio_open_socket_listen(struct roar_vio_calls * calls, int type, char * host, int port) {
360 int fh;
361
362 if ( calls == NULL )
363  return -1;
364
365 if ( (fh = roar_socket_listen(type, host, port)) == -1 )
366  return -1;
367
368 return roar_vio_open_fh_socket(calls, fh);
369}
370
371int     roar_vio_simple_stream (struct roar_vio_calls * calls, int rate, int channels, int bits, int codec,
372                                                               char * server, int dir, char * name) {
373 int fh;
374
375 if ( calls == NULL )
376  return -1;
377
378 roar_libroar_nowarn();
379 if ( (fh = roar_simple_stream(rate, channels, bits, codec, server, dir, name)) == -1 ) {
380  roar_libroar_warn();
381  return -1;
382 }
383 roar_libroar_warn();
384
385 return roar_vio_open_fh_socket(calls, fh);
386}
387
388int     roar_vio_simple_new_stream_obj (struct roar_vio_calls * calls,
389                                        struct roar_connection * con,
390                                        struct roar_stream * s,
391                                        int rate, int channels, int bits, int codec, int dir) {
392 struct roar_stream stream;
393 int fh;
394
395 ROAR_DBG("roar_vio_simple_new_stream_obj(*) = ?");
396
397 if ( calls == NULL )
398  return -1;
399
400 if ( s == NULL )
401  s = &stream;
402
403 roar_libroar_nowarn();
404 if ( (fh = roar_simple_new_stream_obj(con, s, rate, channels, bits, codec, dir)) == -1 ) {
405  roar_libroar_warn();
406  ROAR_DBG("roar_vio_simple_new_stream_obj(*) = -1");
407  return -1;
408 }
409 roar_libroar_warn();
410
411 ROAR_DBG("roar_vio_simple_new_stream_obj(*): fh=%i", fh);
412
413 return roar_vio_open_fh_socket(calls, fh);
414}
415
416// VIOs:
417
418// basic
419ssize_t roar_vio_basic_read (struct roar_vio_calls * vio, void *buf, size_t count) {
420#ifdef _CAN_OPERATE
421 return read(roar_vio_get_fh(vio), buf, count);
422#else
423 return -1;
424#endif
425}
426
427ssize_t roar_vio_basic_write(struct roar_vio_calls * vio, void *buf, size_t count) {
428#ifdef _CAN_OPERATE
429 return write(roar_vio_get_fh(vio), buf, count);
430#else
431 return -1;
432#endif
433}
434
435off_t   roar_vio_basic_lseek(struct roar_vio_calls * vio, off_t offset, int whence) {
436#ifdef _CAN_OPERATE
437 return lseek(roar_vio_get_fh(vio), offset, whence);
438#else
439 return -1;
440#endif
441}
442
443int     roar_vio_basic_nonblock(struct roar_vio_calls * vio, int state) {
444 if ( roar_socket_nonblock(roar_vio_get_fh(vio), state) == -1 )
445  return -1;
446
447 if ( state == ROAR_SOCKET_NONBLOCK )
448  return 0;
449
450 roar_vio_sync(vio);
451
452 return 0;
453}
454
455int     roar_vio_basic_sync    (struct roar_vio_calls * vio) {
456#ifdef ROAR_FDATASYNC
457 return ROAR_FDATASYNC(roar_vio_get_fh(vio));
458#else
459 return 0;
460#endif
461}
462
463int     roar_vio_basic_ctl     (struct roar_vio_calls * vio, int cmd, void * data) {
464#ifdef ROAR_HAVE_H_SYS_IOCTL
465 struct roar_vio_sysio_ioctl * sysioctl;
466#endif
467#if defined(ROAR_HAVE_GETSOCKOPT) || defined(ROAR_HAVE_SETSOCKOPT)
468 struct roar_vio_sysio_sockopt  * syssockopt;
469#endif
470 int tmp;
471 int s_r = 0, s_w = 0;
472#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
473 union {
474  struct sockaddr     sa;
475#if defined(ROAR_HAVE_IPV4) || defined(ROAR_HAVE_IPV6)
476  struct sockaddr_in  in;
477#endif
478#ifdef ROAR_HAVE_UNIX
479  struct sockaddr_un  un;
480#endif
481#ifdef ROAR_HAVE_LIBDNET
482  struct sockaddr_dn  dn;
483#endif
484#ifdef ROAR_HAVE_IPV6
485  struct sockaddr_in6 in6;
486#endif
487#ifdef ROAR_HAVE_IPX
488  struct sockaddr_ipx ipx;
489#endif
490 } sockaddr;
491 socklen_t socklen;
492 struct roar_sockname * rsockname;
493#endif
494
495 if ( vio == NULL || cmd == -1 )
496  return -1;
497
498 ROAR_DBG("roar_vio_basic_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data);
499
500 switch (cmd) {
501  case ROAR_VIO_CTL_GET_NAME:
502    if ( data == NULL )
503     return -1;
504
505    *(char**)data = "basic";
506    return 0;
507   break;
508  case ROAR_VIO_CTL_GET_FH:
509  case ROAR_VIO_CTL_GET_READ_FH:
510  case ROAR_VIO_CTL_GET_WRITE_FH:
511  case ROAR_VIO_CTL_GET_SELECT_FH:
512  case ROAR_VIO_CTL_GET_SELECT_READ_FH:
513  case ROAR_VIO_CTL_GET_SELECT_WRITE_FH:
514    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));
515    *(int*)data = roar_vio_get_fh(vio);
516    return 0;
517   break;
518  case ROAR_VIO_CTL_SET_NOSYNC:
519    vio->sync = NULL;
520    return 0;
521   break;
522  case ROAR_VIO_CTL_ACCEPT:
523    tmp = ROAR_ACCEPT(roar_vio_get_fh(vio), NULL, 0);
524    if ( tmp == -1 )
525     return -1;
526
527    // most proably a socket.
528    if ( roar_vio_open_fh_socket(data, tmp) == -1 ) {
529#ifdef ROAR_TARGET_WIN32
530     closesocket(tmp);
531#else
532     close(tmp);
533#endif
534     return -1;
535    }
536
537    return 0;
538   break;
539  case ROAR_VIO_CTL_SHUTDOWN:
540    tmp = *(int*)data;
541
542    if ( tmp & ROAR_VIO_SHUTDOWN_READ ) {
543     s_r = 1;
544     tmp -= ROAR_VIO_SHUTDOWN_READ;
545    }
546
547    if ( tmp & ROAR_VIO_SHUTDOWN_WRITE ) {
548     s_w = 1;
549     tmp -= ROAR_VIO_SHUTDOWN_WRITE;
550    }
551
552    if ( tmp != 0 ) /* we currently only support R and W shutdowns */
553     return -1;
554
555    if ( s_r && s_w ) {
556     tmp = SHUT_RDWR;
557    } else if ( s_r ) {
558     tmp = SHUT_RD;
559    } else if ( s_w ) {
560     tmp = SHUT_WR;
561    } else {
562     return 0; // nothing to do.
563    }
564
565    return ROAR_SHUTDOWN(roar_vio_get_fh(vio), tmp);
566   break;
567#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
568  case ROAR_VIO_CTL_GET_SOCKNAME:
569  case ROAR_VIO_CTL_GET_PEERNAME:
570    if ( data == NULL )
571     return -1;
572
573    rsockname = data;
574
575    socklen = sizeof(sockaddr);
576
577    if ( cmd == ROAR_VIO_CTL_GET_SOCKNAME ) {
578#ifdef ROAR_HAVE_GETSOCKNAME
579     tmp = getsockname(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
580#else
581     return -1;
582#endif
583    } else if ( cmd == ROAR_VIO_CTL_GET_PEERNAME ) {
584#ifdef ROAR_HAVE_GETPEERNAME
585     tmp = getpeername(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
586#else
587     return -1;
588#endif
589    } else {
590     return -1;
591    }
592
593    if ( tmp == -1 )
594     return -1;
595
596    memset(rsockname, 0, sizeof(struct roar_sockname));
597
598    switch (sockaddr.sa.sa_family) {
599#if defined(AF_UNIX) && defined(ROAR_HAVE_UNIX)
600     case AF_UNIX:
601       rsockname->type = ROAR_SOCKET_TYPE_UNIX;
602       if ( sockaddr.un.sun_path[0] == 0 ) {
603        rsockname->addr = roar_mm_malloc(sizeof(sockaddr.un.sun_path));
604        if ( rsockname->addr == NULL )
605         return -1;
606        memcpy(rsockname->addr, sockaddr.un.sun_path, sizeof(sockaddr.un.sun_path));
607       } else {
608        rsockname->addr = roar_mm_strdup(sockaddr.un.sun_path);
609       }
610      break;
611#endif
612#if defined(AF_DECnet) && defined(ROAR_HAVE_LIBDNET)
613     case AF_DECnet:
614       rsockname->type = ROAR_SOCKET_TYPE_DECNET;
615
616       if ( sockaddr.dn.sdn_add.a_len != 2 )
617        return -1;
618
619       rsockname->addr = roar_mm_malloc(28);
620       if ( rsockname->addr == NULL )
621        return -1;
622
623       snprintf(rsockname->addr, 28, "%i.%i::",
624                 sockaddr.dn.sdn_add.a_addr[1] >> 2,
625                 sockaddr.dn.sdn_add.a_addr[0] + ((sockaddr.dn.sdn_add.a_addr[1] & 0x03) << 8));
626
627       rsockname->port = sockaddr.dn.sdn_objnum;
628       if ( sockaddr.dn.sdn_objnum == 0 ) {
629        tmp = strlen(rsockname->addr);
630        memcpy(rsockname->addr + tmp, sockaddr.dn.sdn_objname, sockaddr.dn.sdn_objnamel);
631        rsockname->addr[tmp + sockaddr.dn.sdn_objnamel] = 0;
632       }
633      break;
634#endif
635#if defined(AF_INET) && (defined(ROAR_HAVE_IPV4) || defined(ROAR_HAVE_IPV6))
636     case AF_INET:
637       rsockname->type = ROAR_SOCKET_TYPE_INET;
638       rsockname->port = ntohs(sockaddr.in.sin_port);
639       rsockname->addr = roar_mm_strdup(inet_ntoa(sockaddr.in.sin_addr));
640      break;
641#endif
642#if defined(AF_INET6) && defined(ROAR_HAVE_IPV6)
643     case AF_INET6:
644       rsockname->type = ROAR_SOCKET_TYPE_INET6;
645       rsockname->port = ntohs(sockaddr.in6.sin6_port);
646      break;
647#endif
648     default:
649       return -1;
650    }
651    return 0;
652#endif
653   break;
654#ifdef ROAR_HAVE_H_SYS_IOCTL
655  case ROAR_VIO_CTL_SYSIO_IOCTL:
656    sysioctl = data;
657    return ioctl(roar_vio_get_fh(vio), sysioctl->cmd, sysioctl->argp);
658   break;
659#endif
660#ifdef ROAR_HAVE_GETSOCKOPT
661  case ROAR_VIO_CTL_GET_SYSIO_SOCKOPT:
662    syssockopt = data;
663    return getsockopt(roar_vio_get_fh(vio), syssockopt->level, syssockopt->optname, syssockopt->optval, &(syssockopt->optlen));
664   break;
665#endif
666#ifdef ROAR_HAVE_SETSOCKOPT
667  case ROAR_VIO_CTL_SET_SYSIO_SOCKOPT:
668    syssockopt = data;
669    return setsockopt(roar_vio_get_fh(vio), syssockopt->level, syssockopt->optname, syssockopt->optval, syssockopt->optlen);
670   break;
671#endif
672 }
673
674 roar_err_set(ROAR_ERROR_BADRQC);
675 return -1;
676}
677
678int     roar_vio_basic_close    (struct roar_vio_calls * vio) {
679#ifdef _CAN_OPERATE
680 if ( roar_vio_get_fh(vio) != -1 )
681  return close(roar_vio_get_fh(vio));
682
683 return 0;
684#else
685 return -1;
686#endif
687}
688
689// null
690ssize_t roar_vio_null_rw    (struct roar_vio_calls * vio, void *buf, size_t count) {
691 if ( vio == NULL || buf == NULL )
692  return -1;
693
694 return 0;
695}
696
697int     roar_vio_null_sync    (struct roar_vio_calls * vio) {
698 return 0;
699}
700
701// pass
702int     roar_vio_open_pass    (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
703 if ( calls == NULL )
704  return -1;
705
706 memset((void*)calls, 0, sizeof(struct roar_vio_calls));
707
708 calls->read     = roar_vio_pass_read;
709 calls->write    = roar_vio_pass_write;
710 calls->lseek    = roar_vio_pass_lseek;
711 calls->nonblock = roar_vio_pass_nonblock;
712 calls->sync     = roar_vio_pass_sync;
713 calls->ctl      = roar_vio_pass_ctl;
714 calls->close    = roar_vio_pass_close;
715
716 calls->inst     = dst;
717
718 return 0;
719}
720
721ssize_t roar_vio_pass_read (struct roar_vio_calls * vio, void *buf, size_t count) {
722 return roar_vio_read((struct roar_vio_calls *) vio->inst, buf, count);
723}
724
725ssize_t roar_vio_pass_write(struct roar_vio_calls * vio, void *buf, size_t count) {
726 return roar_vio_write((struct roar_vio_calls *) vio->inst, buf, count);
727}
728
729off_t   roar_vio_pass_lseek(struct roar_vio_calls * vio, off_t offset, int whence) {
730 return roar_vio_lseek((struct roar_vio_calls *) vio->inst, offset, whence);
731}
732
733int     roar_vio_pass_nonblock(struct roar_vio_calls * vio, int state) {
734 return roar_vio_nonblock((struct roar_vio_calls *) vio->inst, state);
735}
736
737int     roar_vio_pass_sync    (struct roar_vio_calls * vio) {
738 return roar_vio_sync((struct roar_vio_calls *) vio->inst);
739}
740
741int     roar_vio_pass_ctl     (struct roar_vio_calls * vio, int cmd, void * data) {
742 if (vio == NULL || cmd == -1)
743  return -1;
744
745 ROAR_DBG("roar_vio_pass_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data);
746
747 switch (cmd) {
748  case ROAR_VIO_CTL_GET_NAME:
749    if ( data == NULL )
750     return -1;
751
752    // dirty trick to get real name...
753    if ( vio->read == roar_vio_re_read ) {
754     *(char**)data = "re";
755    } else {
756     *(char**)data = "pass";
757    }
758    return 0;
759   break;
760  case ROAR_VIO_CTL_GET_NEXT:
761    *(struct roar_vio_calls **)data = vio->inst;
762    return 0;
763   break;
764  case ROAR_VIO_CTL_SET_NEXT:
765    vio->inst = *(struct roar_vio_calls **)data;
766    return 0;
767   break;
768 }
769
770 return roar_vio_ctl((struct roar_vio_calls *) vio->inst, cmd, data);
771}
772
773int     roar_vio_pass_close   (struct roar_vio_calls * vio) {
774 return roar_vio_close((struct roar_vio_calls *) vio->inst);
775}
776
777
778// re
779int     roar_vio_open_re (struct roar_vio_calls * calls, struct roar_vio_calls * dst) {
780 if ( roar_vio_open_pass(calls, dst) == -1 )
781  return -1;
782
783 calls->read  = roar_vio_re_read;
784 calls->write = roar_vio_re_write;
785 calls->lseek = roar_vio_re_lseek;
786
787 return 0;
788}
789ssize_t roar_vio_re_read (struct roar_vio_calls * vio, void *buf, size_t count) {
790  size_t len =  0;
791 ssize_t r   = -1;
792
793 if ( vio == NULL )
794  return -1;
795
796 if ( vio->inst == NULL )
797  return -1;
798
799 roar_err_clear_all();
800
801 while ( (r = roar_vio_read((struct roar_vio_calls *) vio->inst, buf, count)) > 0 ) {
802  len   += r;
803  buf   += r;
804  count -= r;
805  if ( count == 0 )
806   break;
807 }
808
809 if ( len == 0 && r == -1 )
810  return -1;
811
812 return len;
813}
814
815ssize_t roar_vio_re_write(struct roar_vio_calls * vio, void *buf, size_t count) {
816  size_t len =  0;
817 ssize_t r   = -1;
818
819 if ( vio == NULL )
820  return -1;
821
822 if ( vio->inst == NULL )
823  return -1;
824
825 roar_err_clear_all();
826
827 while ( (r = roar_vio_write((struct roar_vio_calls *) vio->inst, buf, count)) > 0 ) {
828  len   += r;
829  buf   += r;
830  count -= r;
831  if ( count == 0 )
832   break;
833 }
834
835 if ( len == 0 && r == -1 )
836  return -1;
837
838 return len;
839}
840
841// TODO: we should do a some more intelgent thing here.
842off_t   roar_vio_re_lseek(struct roar_vio_calls * vio, off_t offset, int whence) {
843 return roar_vio_lseek((struct roar_vio_calls *) vio->inst, offset, whence);
844}
845
846//ll
Note: See TracBrowser for help on using the repository browser.