source: roaraudio/libroaross/libroaross.c @ 4081:b30bb022564c

Last change on this file since 4081:b30bb022564c was 4081:b30bb022564c, checked in by phi, 14 years ago

added a lot debug lions, fixed broken locking on GNU systems

File size: 54.5 KB
Line 
1//libroaross.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
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 "roaraudio.h"
37#include "libroarlight/libroarlight.h"
38
39#if defined(ROAR_HAVE_OSS_BSD) || defined(ROAR_HAVE_OSS)
40#if defined(__OpenBSD__) || defined(__NetBSD__)
41#include <soundcard.h>
42#else
43#include <sys/soundcard.h>
44#endif
45#include <sys/ioctl.h>
46
47#ifdef ROAR_HAVE_H_SYS_TYPES
48#include <sys/types.h>
49#endif
50
51#ifdef ROAR_HAVE_H_FCNTL
52#include <fcntl.h>
53#endif
54
55#ifdef ROAR_HAVE_H_UNISTD
56#include <unistd.h>
57#endif
58
59#include <sys/stat.h>
60#include <dlfcn.h>
61#include <stdarg.h>
62
63#if defined(RTLD_NEXT)
64#define REAL_LIBC RTLD_NEXT
65#else
66#define REAL_LIBC ((void *) -1L)
67#endif
68
69#ifndef ENOTSUP
70#define ENOTSUP ENOSYS
71#endif
72
73#ifndef O_DIRECTORY
74#define O_DIRECTORY 0
75#endif
76
77#ifndef O_DIRECT
78#define O_DIRECT 0
79#endif
80
81#ifndef O_LARGEFILE
82#define O_LARGEFILE 0
83#endif
84
85#ifndef O_NOATIME
86#define O_NOATIME 0
87#endif
88
89#define _O_PARA_DIR (O_RDONLY|O_WRONLY|O_RDWR)
90#define _O_PARA_IGN (O_DIRECT|O_APPEND|O_LARGEFILE|O_NOATIME|O_NOCTTY|O_TRUNC)
91
92#if defined(ROAR_OS_NETBSD) && defined(ioctl)
93#define IOCTL_IS_ALIAS
94#endif
95
96#ifdef ROAR_OS_FREEBSD
97#define _VA_ARGS_MODE_T int
98#else
99#define _VA_ARGS_MODE_T mode_t
100#endif
101
102#ifdef ROAR_OS_FREEBSD
103#define _CREAT_ARG_PATHNAME path
104#else
105#define _CREAT_ARG_PATHNAME pathname
106#endif
107
108#ifdef ROAR_OS_NETBSD
109#define IOCTL() int _oss_ioctl __P((int fd, unsigned long com, void *argp))
110#define map_args int __fd = fd; unsigned long int __request = com
111#elif defined(ROAR_TARGET_CYGWIN)
112#define IOCTL() int ioctl (int __fd, int __cmd, ...)
113#define map_args unsigned long int __request = __cmd; void * argp
114#define va_argp
115#define ioctl_lastarg __cmd
116#else
117#define IOCTL() int ioctl (int __fd, unsigned long int __request, ...)
118#define map_args void * argp
119#define va_argp
120#define ioctl_lastarg __request
121#endif
122
123#define OSS_VOLUME_SCALE 100
124
125#define _MAX_POINTER  8
126
127// handle type:
128#define HT_NONE       0 /* Unused object */
129#define HT_STREAM     1 /* Stream with no specal handling needed */
130#define HT_MIXER      2 /* Mixer device */
131#define HT_WAVEFORM   3 /* Waveform device */
132#define HT_MIDI       4 /* MIDI device */
133#define HT_DMX        5 /* DMX512/DMX4Linux device */
134#define HT_VIO        6 /* General VIO object */
135#define HT_STATIC     7 /* Static file */
136
137struct session {
138 int refc;
139 struct roar_connection con;
140};
141
142static struct session _session = {.refc = 0};
143
144struct handle {
145 int refc; // refrence counter
146 struct session * session;
147 int type;
148 int sysio_flags;
149 struct roar_stream    stream;
150 struct roar_vio_calls stream_vio;
151 int                   stream_dir;
152 int                   stream_opened;
153 size_t                stream_buffersize;
154 size_t                readc, writec;
155 size_t                pos;
156 union {
157  struct {
158   char * data;
159   size_t len;
160  } sf;
161 } userdata;
162};
163
164static struct {
165 int     (*open)(const char *pathname, int flags, mode_t mode);
166 int     (*close)(int fd);
167 ssize_t (*write)(int fd, const void *buf, size_t count);
168 ssize_t (*read)(int fd, void *buf, size_t count);
169#ifndef IOCTL_IS_ALIAS
170 int     (*ioctl)(int d, int request, ...);
171#endif
172 off_t   (*lseek)(int fildes, off_t offset, int whence);
173 FILE   *(*fopen)(const char *path, const char *mode);
174 int     (*dup)(int oldfd);
175 int     (*dup2)(int oldfd, int newfd);
176 int     (*select)(int nfds, fd_set *readfds, fd_set *writefds,
177                   fd_set *exceptfds, struct timeval *timeout);
178 int     (*fcntl)(int fd, int cmd, ...);
179 int     (*access)(const char *pathname, int mode);
180 int     (*open64)(const char *__file, int __oflag, ...);
181 int     (*creat)(const char *_CREAT_ARG_PATHNAME, mode_t mode);
182 int     (*stat)(const char *path, struct stat *buf);
183 int     (*fstat)(int filedes, struct stat *buf);
184 int     (*lstat)(const char *path, struct stat *buf);
185} _os;
186
187static struct {
188 struct {
189  int volume;
190  int pcm;
191  int line;
192  int line1;
193  int line2;
194  int line3;
195  int digital1;
196  int digital2;
197  int digital3;
198 } sid;
199} _mix_settings = {
200                   .sid = {
201                           .volume   = -1,
202                           .pcm      = -1,
203                           .line     =  0,
204                           .line1    =  1,
205                           .line2    =  2,
206                           .line3    =  3,
207                           .digital1 =  1,
208                           .digital2 =  2,
209                           .digital3 =  3
210                          }
211                  };
212
213static struct pointer {
214 int fh;
215 struct handle * handle;
216} _ptr[_MAX_POINTER];
217
218
219static char _sf__dev_sndstat[] =
220 "Sound Driver:RoarAudio\n"
221 "Config options: 0\n"
222 "\n"
223 "Installed drivers:\n"
224 "Type 10: RoarAudio emulation\n"
225 "\n"
226 "Card config:\n"
227 "\n"
228 "Audio devices:\n"
229 "0: RoarAudio OSS emulation (DUPLEX)\n"
230 "\n"
231 "Midi devices:\n"
232 "0: RoarAudio OSS emulation MIDI\n"
233 "\n"
234 "Timers:\n"
235 "\n"
236 "Mixers:\n"
237 "0: RoarAudio OSS emulation Mixer\n"
238;
239
240static struct devices {
241  char * prefix;
242  int type;
243  size_t len;
244  void * userdata;
245  struct handle * (*open)(const char * file, int flags, mode_t mode, struct devices * ptr);
246} _device_list[] = {
247 {"/dev/dsp",           HT_WAVEFORM,  0, NULL, NULL},
248 {"/dev/dsp?",          HT_WAVEFORM,  0, NULL, NULL},
249 {"/dev/audio",         HT_WAVEFORM,  0, NULL, NULL},
250 {"/dev/audio?",        HT_WAVEFORM,  0, NULL, NULL},
251 {"/dev/sound/dsp",     HT_WAVEFORM,  0, NULL, NULL},
252 {"/dev/sound/dsp?",    HT_WAVEFORM,  0, NULL, NULL},
253 {"/dev/sound/audio",   HT_WAVEFORM,  0, NULL, NULL},
254 {"/dev/sound/audio?",  HT_WAVEFORM,  0, NULL, NULL},
255 {"/dev/mixer",         HT_MIXER,     0, NULL, NULL},
256 {"/dev/mixer?",        HT_MIXER,     0, NULL, NULL},
257 {"/dev/sound/mixer",   HT_MIXER,     0, NULL, NULL},
258 {"/dev/sound/mixer?",  HT_MIXER,     0, NULL, NULL},
259 {"/dev/midi",          HT_MIDI,      0, NULL, NULL},
260 {"/dev/midi?",         HT_MIDI,      0, NULL, NULL},
261 {"/dev/rmidi",         HT_MIDI,      0, NULL, NULL},
262 {"/dev/rmidi?",        HT_MIDI,      0, NULL, NULL},
263 {"/dev/sound/midi",    HT_MIDI,      0, NULL, NULL},
264 {"/dev/sound/midi?",   HT_MIDI,      0, NULL, NULL},
265 {"/dev/sound/rmidi",   HT_MIDI,      0, NULL, NULL},
266 {"/dev/sound/rmidi?",  HT_MIDI,      0, NULL, NULL},
267 {"/dev/dmx",           HT_DMX,       0, NULL, NULL},
268 {"/dev/dmx?",          HT_DMX,       0, NULL, NULL},
269 {"/dev/misc/dmx",      HT_DMX,       0, NULL, NULL},
270 {"/dev/misc/dmx?",     HT_DMX,       0, NULL, NULL},
271 {"/dev/dmxin",         HT_DMX,       0, NULL, NULL},
272 {"/dev/dmxin?",        HT_DMX,       0, NULL, NULL},
273 {"/dev/misc/dmxin",    HT_DMX,       0, NULL, NULL},
274 {"/dev/misc/dmxin?",   HT_DMX,       0, NULL, NULL},
275 {"/dev/sndstat",       HT_STATIC,    sizeof(_sf__dev_sndstat)-1, _sf__dev_sndstat, NULL},
276#ifdef ROAR_DEFAULT_OSS_DEV
277 {ROAR_DEFAULT_OSS_DEV, HT_WAVEFORM,  0, NULL, NULL},
278#endif
279 {NULL, HT_NONE, 0, NULL, NULL},
280};
281
282
283static int _update_nonblock (struct handle * handle);
284
285static void _init_os (void) {
286 memset(&_os, 0, sizeof(_os));
287
288 // if call roar_dl_getsym() here all applications will segfaul.
289 // why?
290
291 _os.open   = dlsym(REAL_LIBC, "open");
292 _os.close  = dlsym(REAL_LIBC, "close");
293 _os.write  = dlsym(REAL_LIBC, "write");
294 _os.read   = dlsym(REAL_LIBC, "read");
295#ifndef IOCTL_IS_ALIAS
296 _os.ioctl  = dlsym(REAL_LIBC, "ioctl");
297#endif
298 _os.lseek  = dlsym(REAL_LIBC, "lseek");
299 _os.fopen  = dlsym(REAL_LIBC, "fopen");
300 _os.dup    = dlsym(REAL_LIBC, "dup");
301 _os.dup2   = dlsym(REAL_LIBC, "dup2");
302 _os.select = dlsym(REAL_LIBC, "select");
303 _os.fcntl  = dlsym(REAL_LIBC, "fcntl");
304 _os.access = dlsym(REAL_LIBC, "access");
305 _os.open64 = dlsym(REAL_LIBC, "open64");
306 _os.creat  = dlsym(REAL_LIBC, "creat");
307 _os.stat   = dlsym(REAL_LIBC, "stat");
308 _os.fstat  = dlsym(REAL_LIBC, "fstat");
309 _os.lstat  = dlsym(REAL_LIBC, "lstat");
310}
311
312static void _init_ptr (void) {
313 int i;
314
315 for (i = 0; i < _MAX_POINTER; i++) {
316  _ptr[i].fh = -1;
317 }
318}
319
320static void _init (void) {
321 static int inited = 0;
322
323 if ( !inited ) {
324  _init_os();
325  _init_ptr();
326  roar_vio_select(NULL, 0, NULL, NULL);
327  inited++;
328 }
329}
330
331static void _find_volume_sid (struct session * session) {
332 int i;
333 int num;
334 int id[ROAR_STREAMS_MAX];
335 struct roar_stream s;
336 char name[1024];
337
338 ROAR_DBG("_find_volume_sid(session=%p) = ?", session);
339
340 if ( (num = roar_list_streams(&(session->con), id, ROAR_STREAMS_MAX)) == -1 ) {
341  return;
342 }
343
344 for (i = 0; i < num; i++) {
345  if ( roar_get_stream(&(session->con), &s, id[i]) == -1 )
346   continue;
347
348  if ( s.dir != ROAR_DIR_MIXING )
349   continue;
350
351  if ( roar_stream_get_name(&(session->con), &s, name, 1024) == -1 )
352   continue;
353
354  if ( !strcasecmp(name, "Waveform Mixer") ) {
355   _mix_settings.sid.volume = id[i];
356   ROAR_DBG("_find_volume_sid(session=%p): found waveform mixer at sid %i", session, id[i]);
357   ROAR_DBG("_find_volume_sid(session=%p) = (void)", session);
358   return;
359  }
360 }
361}
362
363static int _open_dummy (void) {
364 int p[2];
365
366 ROAR_DBG("_open_dummy(void) = ?");
367
368 if ( pipe(p) == -1 )
369  return -1;
370
371 close(p[1]);
372
373 ROAR_DBG("_open_dummy(void) = %i", p[0]);
374 return p[0];
375}
376
377static struct session * _open_session (char * server, char * name) {
378 struct session * ses = &_session;
379 int new_session = getenv("ROAR_OSS_NEW_SESSION") == NULL ? 0 : 1;
380
381 ROAR_DBG("_open_session(server='%s', name='%s') = ?", server, name);
382 ROAR_DBG("_open_session(server='%s', name='%s'): _session.refc=%i", server, name, _session.refc);
383
384 if ( new_session ) {
385  ses = roar_mm_malloc(sizeof(struct session));
386  if ( ses == NULL )
387   return NULL;
388
389  memset(ses, 0, sizeof(struct session));
390 }
391
392 if ( ses->refc == 0 ) {
393
394  if ( name == NULL )
395   name = getenv("ROAR_OSS_CLIENT_NAME");
396
397  if ( name == NULL )
398   name = "libroaross client";
399
400  if ( roar_simple_connect(&(ses->con), server, name) == -1 ) {
401   if ( new_session )
402    roar_mm_free(ses);
403
404   return NULL;
405  }
406
407  _find_volume_sid(ses);
408
409  if ( !new_session ) {
410   if ( getenv("ROAR_OSS_KEEP_SESSION") != NULL )
411    ses->refc++;
412  }
413 }
414
415 ses->refc++;
416
417 ROAR_DBG("_open_session(server='%s', name='%s') = %p", server, name, ses);
418 return ses;
419}
420
421static void _close_session(struct session * session) {
422 if ( session == NULL )
423  return;
424
425 session->refc--;
426
427 ROAR_DBG("_close_session(session=%p): session->refc=%i", session, session->refc);
428
429 if ( session->refc == 0 ) {
430  roar_disconnect(&(session->con));
431 }
432
433 if ( session != &_session )
434  roar_mm_free(session);
435}
436
437static struct handle * _open_handle(struct session * session) {
438 struct handle * handle;
439
440 ROAR_DBG("_open_handle(session=%p) = ?", session);
441
442 if ( (handle = roar_mm_malloc(sizeof(struct handle))) == NULL )
443  return NULL;
444
445 memset(handle, 0, sizeof(struct handle));
446
447 handle->refc = 1;
448 handle->session = session;
449
450 if ( session != NULL )
451  session->refc++; // TODO: better warp this
452
453 handle->type = HT_NONE;
454 handle->stream_dir = ROAR_DIR_PLAY;
455 roar_stream_new(&(handle->stream), ROAR_RATE_DEFAULT, ROAR_CHANNELS_DEFAULT, ROAR_BITS_DEFAULT, ROAR_CODEC_DEFAULT);
456
457 ROAR_DBG("_open_handle(session=%p) = %p", session, handle);
458 return handle;
459}
460
461static void _close_handle(struct handle * handle) {
462 int need_close = 0;
463
464 if (handle == NULL)
465  return;
466
467 handle->refc--;
468
469 ROAR_DBG("_close_handle(handle=%p): handle->refc=%i", handle, handle->refc);
470
471 if ( handle->refc == 0 ) {
472  switch (handle->type) {
473   case HT_VIO:
474     need_close = 1;
475    break;
476   case HT_STREAM:
477     if ( handle->stream_opened )
478      need_close = 1;
479    break;
480  }
481
482  if ( need_close )
483   roar_vio_close(&(handle->stream_vio));
484
485  if ( handle->session != NULL ) {
486   handle->session->refc--;
487
488   _close_session(handle->session);
489  }
490
491  roar_mm_free(handle);
492 }
493}
494
495static struct pointer * _get_pointer_by_fh_or_new (int fh) {
496 int i;
497
498 for (i = 0; i < _MAX_POINTER; i++) {
499  if ( _ptr[i].fh == fh )
500   return &(_ptr[i]);
501 }
502
503 return NULL;
504}
505
506static struct pointer * _get_pointer_by_fh (int fh) {
507 if ( fh == -1 )
508  return NULL;
509
510 return _get_pointer_by_fh_or_new(fh);
511}
512
513static struct pointer * _open_pointer(struct handle * handle) {
514 struct pointer * ret = _get_pointer_by_fh_or_new(-1);
515
516 ROAR_DBG("_open_pointer(handle=%p) = ?", handle);
517
518 if ( ret == NULL ) {
519  ROAR_DBG("_open_pointer(handle=%p) = NULL", handle);
520  return NULL;
521 }
522
523 if ( (ret->fh = _open_dummy()) == -1 ) {
524  ROAR_DBG("_open_pointer(handle=%p) = NULL", handle);
525  return NULL;
526 }
527
528 ret->handle = handle;
529
530 ROAR_DBG("_open_pointer(handle=%p) = %p", handle, ret);
531
532 return ret;
533}
534
535static struct pointer * _attach_pointer(struct handle * handle, int fh) {
536 struct pointer * ret = _get_pointer_by_fh_or_new(-1);
537
538 if ( ret == NULL )
539  return NULL;
540
541 if ( (ret->fh = fh) == -1 )
542  return NULL;
543
544 ret->handle = handle;
545
546 handle->refc++;
547
548 return ret;
549}
550
551static void _close_pointer(struct pointer * pointer) {
552 if ( pointer == NULL )
553  return;
554
555 _os.close(pointer->fh);
556
557 pointer->fh = -1;
558
559 _close_handle(pointer->handle);
560}
561
562// -------------------------------------
563// central function to find device:
564// -------------------------------------
565
566static struct devices * _get_device (const char * pathname) {
567 size_t len, pathlen;
568 int i;
569 int qm_match;
570
571 ROAR_DBG("_get_device(pathname='%s') = ?", pathname);
572
573 pathlen = strlen(pathname);
574
575 for (i = 0; _device_list[i].prefix != NULL; i++) {
576  len = strlen(_device_list[i].prefix);
577
578  qm_match = 0;
579
580  if ( _device_list[i].prefix[len-1] == '*' ) {
581   len--;
582  } else if ( _device_list[i].prefix[len-1] == '?' ) {
583   qm_match = 1;
584   len--;
585  } else {
586   len++;
587  }
588
589  if ( !strncmp(pathname, _device_list[i].prefix, len) ) {
590   if ( !qm_match || pathlen == (len + 1) )
591    return &(_device_list[i]);
592  }
593 }
594
595 ROAR_DBG("_get_device(pathname='%s') = NULL", pathname);
596 return NULL;
597}
598
599// -------------------------------------
600// central open function:
601// -------------------------------------
602
603static int _open_file (const char *pathname, int flags) {
604 struct session * session;
605 struct handle  * handle;
606 struct pointer * pointer;
607 struct devices * ptr = NULL;
608
609 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
610
611/*
612 * Flags we ignore:
613 * O_DIRECT, O_APPEND, O_LARGEFILE, O_NOATIME, O_NOCTTY, O_TRUNC
614 */
615
616 if ( (ptr = _get_device(pathname)) == NULL ) {
617  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -2", pathname, flags);
618  return -2;
619 }
620
621 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
622
623
624#ifdef O_ASYNC
625 if ( flags & O_ASYNC ) {
626  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1 // not supported O_ASYNC", pathname, flags);
627  errno = ENOSYS;
628  return -1;
629 }
630#endif
631
632 if ( (flags & O_DIRECTORY) || (flags & O_EXCL) ) {
633  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1 // invalid flags (O_DIRECTORY or O_EXCL)", pathname, flags);
634  errno = EINVAL;
635  return -1;
636 }
637
638 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
639
640 if ( ptr->type == HT_STATIC || ptr->type == HT_VIO ) { // non-session handles
641  session = NULL;
642 } else {
643  if ( (session = _open_session(NULL, NULL)) == NULL ) {
644   ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
645   return -1;
646  }
647 }
648
649 if ( ptr->open != NULL ) {
650  // TODO: Add support to pass mode (perms) to open.
651  if ( (handle = ptr->open(pathname, flags, 0000, ptr)) == NULL ) {
652   _close_session(session);
653   ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
654   return -1;
655  }
656 } else {
657  if ( (handle = _open_handle(session)) == NULL ) {
658   _close_session(session);
659   ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
660   return -1;
661  }
662
663  handle->type        = ptr->type;
664  handle->sysio_flags = flags;
665  handle->stream_dir  = -1;
666 }
667
668 switch (flags & _O_PARA_DIR) {
669  case O_RDONLY:
670    switch (ptr->type) {
671     case HT_WAVEFORM:
672       handle->stream_dir = ROAR_DIR_MONITOR;
673      break;
674     case HT_MIDI:
675       handle->stream_dir = ROAR_DIR_MIDI_OUT;
676      break;
677     case HT_DMX:
678       handle->stream_dir = ROAR_DIR_LIGHT_OUT;
679      break;
680     case HT_MIXER:
681     case HT_STATIC:
682      break;
683     default:
684       ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
685       return -1;
686    }
687   break;
688  case O_WRONLY:
689    switch (ptr->type) {
690     case HT_WAVEFORM:
691       handle->stream_dir = ROAR_DIR_PLAY;
692      break;
693     case HT_MIDI:
694       handle->stream_dir = ROAR_DIR_MIDI_IN;
695      break;
696     case HT_DMX:
697       handle->stream_dir = ROAR_DIR_LIGHT_IN;
698      break;
699     case HT_MIXER:
700     case HT_STATIC:
701      break;
702     default:
703       ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
704       return -1;
705    }
706   break;
707  case O_RDWR:
708    switch (ptr->type) {
709     case HT_WAVEFORM:
710       handle->stream_dir = ROAR_DIR_BIDIR;
711      break;
712     case HT_MIXER:
713     case HT_STATIC:
714      break;
715     default:
716       ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
717       return -1;
718    }
719   break;
720 }
721
722 switch (handle->type) {
723  case HT_WAVEFORM:
724    handle->type = HT_STREAM;
725   break;
726  case HT_MIDI:
727    handle->type = HT_STREAM;
728    handle->stream.info.rate     = 0;
729    handle->stream.info.bits     = ROAR_MIDI_BITS;
730    handle->stream.info.channels = ROAR_MIDI_CHANNELS_DEFAULT;
731    handle->stream.info.codec    = ROAR_CODEC_MIDI;
732   break;
733  case HT_DMX:
734    handle->stream.info.rate     = 0;
735    handle->stream.info.bits     = ROAR_LIGHT_BITS;
736    handle->stream.info.channels = 512;
737    handle->stream.info.codec    = ROAR_CODEC_ROARDMX;
738   break;
739  case HT_STATIC:
740    handle->userdata.sf.len      = ptr->len;
741    handle->userdata.sf.data     = ptr->userdata;
742   break;
743 }
744
745 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
746
747 if ( (pointer = _open_pointer(handle)) == NULL ) {
748  _close_handle(handle);
749  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
750  return -1;
751 }
752
753 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = %i", pathname, flags, pointer->fh);
754
755 return pointer->fh;
756}
757
758// -------------------------------------
759// VIO open function:
760// -------------------------------------
761
762int libroaross_open_vio(struct handle ** handleret, struct roar_vio_calls ** vio, int flags) {
763 struct handle  * handle;
764 struct pointer * pointer;
765
766 _init();
767
768 if ( vio == NULL )
769  return -1;
770
771 if ( (handle = _open_handle(NULL)) == NULL ) {
772  return -1;
773 }
774
775 handle->type        = HT_VIO;
776 handle->sysio_flags = flags;
777
778 if ( roar_vio_init_calls(&(handle->stream_vio)) == -1 ) {
779  _close_handle(handle);
780  return -1;
781 }
782
783 *vio = &(handle->stream_vio);
784
785 if ( handleret != NULL )
786  *handleret = handle;
787
788 if ( (pointer = _open_pointer(handle)) == NULL ) {
789  _close_handle(handle);
790  return -1;
791 }
792
793 return pointer->fh;
794}
795
796// -------------------------------------
797// open function for streams:
798// -------------------------------------
799
800static int _open_stream (struct handle * handle) {
801  // FIXME: this should be re-written much more cleanly:
802
803 if ( handle == NULL )
804  return -1;
805
806 if ( roar_vio_simple_new_stream_obj(&(handle->stream_vio),
807                                     &(handle->session->con), &(handle->stream),
808                                     handle->stream.info.rate,
809                                     handle->stream.info.channels,
810                                     handle->stream.info.bits,
811                                     handle->stream.info.codec,
812                                     handle->stream_dir
813                                    ) == -1 )
814  return -1;
815
816 handle->stream_opened++;
817
818 _mix_settings.sid.pcm = roar_stream_get_id(&(handle->stream));
819
820 _update_nonblock(handle);
821
822 return 0;
823}
824
825// -------------------------------------
826// function to update O_NONBLOCK:
827// -------------------------------------
828
829static int _update_nonblock (struct handle * handle) {
830 int opened = 0;
831 int state  = handle->sysio_flags & O_NONBLOCK ? ROAR_SOCKET_NONBLOCK : ROAR_SOCKET_BLOCK;
832
833 switch (handle->type) {
834  case HT_NONE:
835  case HT_STATIC:
836  case HT_MIXER:
837    // we can ignore setting of nonblock flag here.
838    return 0;
839   break;
840  case HT_VIO:
841    opened = 1;
842   break;
843  case HT_STREAM:
844  case HT_WAVEFORM:
845  case HT_MIDI:
846  case HT_DMX:
847    opened = handle->stream_opened;
848   break;
849 }
850
851 if ( opened ) {
852  return roar_vio_nonblock(&(handle->stream_vio), state);
853 }
854
855 return 0;
856}
857
858// -------------------------------------
859// function to parse format:
860// -------------------------------------
861
862static int _ioctl_stream_format (struct handle * handle, int format) {
863 struct roar_audio_info * info = &(handle->stream.info);
864
865 switch (format) {
866  case AFMT_S8:
867    info->bits  = 8;
868    info->codec = ROAR_CODEC_PCM_S_LE;
869   break;
870  case AFMT_U8:
871    info->bits  = 8;
872    info->codec = ROAR_CODEC_PCM_U_LE;
873   break;
874  case AFMT_S16_BE:
875    info->bits  = 16;
876    info->codec = ROAR_CODEC_PCM_S_BE;
877   break;
878  case AFMT_S16_LE:
879    info->bits  = 16;
880    info->codec = ROAR_CODEC_PCM_S_LE;
881   break;
882  case AFMT_U16_BE:
883    info->bits  = 16;
884    info->codec = ROAR_CODEC_PCM_U_BE;
885   break;
886  case AFMT_U16_LE:
887    info->bits  = 16;
888    info->codec = ROAR_CODEC_PCM_U_LE;
889   break;
890#ifdef AFMT_S32_BE
891  case AFMT_S32_BE:
892    info->bits  = 32;
893    info->codec = ROAR_CODEC_PCM_S_BE;
894   break;
895#endif
896#ifdef AFMT_S32_LE
897  case AFMT_S32_LE:
898    info->bits  = 32;
899    info->codec = ROAR_CODEC_PCM_S_LE;
900   break;
901#endif
902  case AFMT_A_LAW:
903    info->bits  = 8;
904    info->codec = ROAR_CODEC_ALAW;
905   break;
906  case AFMT_MU_LAW:
907    info->bits  = 8;
908    info->codec = ROAR_CODEC_MULAW;
909   break;
910#ifdef AFMT_VORBIS
911  case AFMT_VORBIS:
912    info->codec = ROAR_CODEC_OGG_VORBIS;
913   break;
914#endif
915  default:
916    ROAR_DBG("_ioctl_stream_format(*): unsupported format");
917    errno = ENOSYS;
918    return -1;
919   break;
920 }
921
922 return 0;
923}
924
925static inline int _ioctl_stream_format_list (void) {
926 int format = 0;
927
928 format |= AFMT_S8;
929 format |= AFMT_U8;
930
931 format |= AFMT_S16_BE;
932 format |= AFMT_S16_LE;
933
934 format |= AFMT_U16_BE;
935 format |= AFMT_U16_LE;
936
937#ifdef AFMT_S32_BE
938 format |= AFMT_S32_BE;
939#endif
940#ifdef AFMT_S32_LE
941 format |= AFMT_S32_LE;
942#endif
943
944 format |= AFMT_A_LAW;
945 format |= AFMT_MU_LAW;
946
947#ifdef AFMT_VORBIS
948 format |= AFMT_VORBIS;
949#endif
950
951 return format;
952}
953
954// -------------------------------------
955// mixer ioctls:
956// -------------------------------------
957
958static int _ioctl_mixer (struct handle * handle, long unsigned int req, void * vp) {
959 mixer_info * info;
960 int channels;
961 struct roar_mixer_settings mixer;
962 int o_w    =  0;
963 int o_sid  = -1;
964 int * ip   = vp;
965#if defined(DEBUG) && defined(DEBUG_IOCTL_NAMES)
966 char * name = NULL;
967#endif
968
969#if defined(DEBUG) && defined(DEBUG_IOCTL_NAMES)
970 switch (req) {
971#if 0
972  case SNDCTL_MIX_DESCRIPTION: name = "SNDCTL_MIX_DESCRIPTION"; break;
973  case SNDCTL_MIX_ENUMINFO:    name = "SNDCTL_MIX_ENUMINFO";    break;
974  case SNDCTL_MIX_EXTINFO:     name = "SNDCTL_MIX_EXTINFO";     break;
975  case SNDCTL_MIX_NREXT:       name = "SNDCTL_MIX_NREXT";       break;
976  case SNDCTL_MIX_NRMIX:       name = "SNDCTL_MIX_NRMIX";       break;
977  case SNDCTL_MIX_READ:        name = "SNDCTL_MIX_READ";        break;
978  case SNDCTL_MIX_WRITE:       name = "SNDCTL_MIX_WRITE";       break;
979#endif
980//  case SOUND_MIXER_INFO:             name = "SOUND_MIXER_INFO";             break;
981  case SOUND_OLD_MIXER_INFO:         name = "SOUND_OLD_MIXER_INFO";         break;
982  case SOUND_MIXER_ACCESS:           name = "SOUND_MIXER_ACCESS";           break;
983  case SOUND_MIXER_AGC:              name = "SOUND_MIXER_AGC";              break;
984  case SOUND_MIXER_3DSE:             name = "SOUND_MIXER_3DSE";             break;
985  case SOUND_MIXER_GETLEVELS:        name = "SOUND_MIXER_GETLEVELS";        break;
986  case SOUND_MIXER_SETLEVELS:        name = "SOUND_MIXER_SETLEVELS";        break;
987  case SOUND_MIXER_PRIVATE1:         name = "SOUND_MIXER_PRIVATE1";         break;
988  case SOUND_MIXER_PRIVATE2:         name = "SOUND_MIXER_PRIVATE2";         break;
989  case SOUND_MIXER_PRIVATE3:         name = "SOUND_MIXER_PRIVATE3";         break;
990  case SOUND_MIXER_PRIVATE4:         name = "SOUND_MIXER_PRIVATE4";         break;
991  case SOUND_MIXER_PRIVATE5:         name = "SOUND_MIXER_PRIVATE5";         break;
992  case OSS_GETVERSION:               name = "OSS_GETVERSION";               break;
993//  case SOUND_MIXER_READ_CAPS:        name = "SOUND_MIXER_READ_CAPS";        break;
994  case SOUND_MIXER_READ_MUTE:        name = "SOUND_MIXER_READ_MUTE";        break;
995/*
996  case :     name = "";     break;
997  case :     name = "";     break;
998*/
999 }
1000 if ( name != NULL ) {
1001  ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p): unspported mixer command %s", handle, req, ip, name);
1002  ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
1003  errno = ENOSYS;
1004  return -1;
1005 }
1006#endif
1007
1008 switch (req) {
1009  case SOUND_MIXER_READ_VOLUME:    o_w = 0; o_sid = _mix_settings.sid.volume;   break;
1010  case SOUND_MIXER_READ_LINE:      o_w = 0; o_sid = _mix_settings.sid.line;     break;
1011  case SOUND_MIXER_READ_LINE1:     o_w = 0; o_sid = _mix_settings.sid.line1;    break;
1012  case SOUND_MIXER_READ_LINE2:     o_w = 0; o_sid = _mix_settings.sid.line2;    break;
1013  case SOUND_MIXER_READ_LINE3:     o_w = 0; o_sid = _mix_settings.sid.line3;    break;
1014#if 0
1015  case SOUND_MIXER_READ_DIGITAL1:  o_w = 0; o_sid = _mix_settings.sid.digital1; break;
1016  case SOUND_MIXER_READ_DIGITAL2:  o_w = 0; o_sid = _mix_settings.sid.digital2; break;
1017  case SOUND_MIXER_READ_DIGITAL3:  o_w = 0; o_sid = _mix_settings.sid.digital3; break;
1018#endif
1019  case SOUND_MIXER_WRITE_VOLUME:   o_w = 1; o_sid = _mix_settings.sid.volume;   break;
1020  case SOUND_MIXER_WRITE_LINE:     o_w = 1; o_sid = _mix_settings.sid.line;     break;
1021  case SOUND_MIXER_WRITE_LINE1:    o_w = 1; o_sid = _mix_settings.sid.line1;    break;
1022  case SOUND_MIXER_WRITE_LINE2:    o_w = 1; o_sid = _mix_settings.sid.line2;    break;
1023  case SOUND_MIXER_WRITE_LINE3:    o_w = 1; o_sid = _mix_settings.sid.line3;    break;
1024#if 0
1025  case SOUND_MIXER_WRITE_DIGITAL1: o_w = 1; o_sid = _mix_settings.sid.digital1; break;
1026  case SOUND_MIXER_WRITE_DIGITAL2: o_w = 1; o_sid = _mix_settings.sid.digital2; break;
1027  case SOUND_MIXER_WRITE_DIGITAL3: o_w = 1; o_sid = _mix_settings.sid.digital3; break;
1028#endif
1029  // we handle PCM seperatly as we want to be abled to abled to handle it on a stream (not mixer), too:
1030  case SOUND_MIXER_READ_PCM:
1031    o_w = 0;
1032    if ( handle->type == HT_STREAM ) {
1033     o_sid = roar_stream_get_id(&(handle->stream));
1034    } else {
1035     o_sid = _mix_settings.sid.pcm;
1036    }
1037   break;
1038  case SOUND_MIXER_WRITE_PCM:
1039    o_w = 1;
1040    if ( handle->type == HT_STREAM ) {
1041     o_sid = roar_stream_get_id(&(handle->stream));
1042    } else {
1043     o_sid = _mix_settings.sid.pcm;
1044    }
1045   break;
1046 }
1047 if ( o_sid != -1 ) {
1048  // set/get volume
1049  if ( o_w ) {
1050   mixer.scale    = OSS_VOLUME_SCALE;
1051   mixer.mixer[0] = ( *ip       & 0xFF);
1052   mixer.mixer[1] = ((*ip >> 8) & 0xFF);
1053   if ( roar_set_vol(&(handle->session->con), o_sid, &mixer, 2) == -1 ) {
1054    errno = EIO;
1055    return -1;
1056   }
1057   return 0;
1058  } else {
1059   if ( roar_get_vol(&(handle->session->con), o_sid, &mixer, &channels) == -1 ) {
1060    errno = EIO;
1061    return -1;
1062   }
1063   *ip = ((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale) | (((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale)<<8);
1064   return 0;
1065  }
1066 }
1067
1068 switch (req) {
1069  case SOUND_MIXER_READ_STEREODEVS: /* FIXME: check the streams for channel config */
1070  case SOUND_MIXER_READ_DEVMASK:
1071    *ip = 0;
1072
1073    if ( _mix_settings.sid.volume != -1 )
1074     *ip |= SOUND_MASK_VOLUME;
1075    if ( _mix_settings.sid.pcm != -1 )
1076     *ip |= SOUND_MASK_PCM;
1077    if ( _mix_settings.sid.line != -1 )
1078     *ip |= SOUND_MASK_LINE;
1079    if ( _mix_settings.sid.line1 != -1 )
1080     *ip |= SOUND_MASK_LINE1;
1081    if ( _mix_settings.sid.line2 != -1 )
1082     *ip |= SOUND_MASK_LINE2;
1083    if ( _mix_settings.sid.line3 != -1 )
1084     *ip |= SOUND_MASK_LINE3;
1085    if ( _mix_settings.sid.digital1 != -1 )
1086#if 0
1087     *ip |= SOUND_MASK_DIGITAL1;
1088    if ( _mix_settings.sid.digital2 != -1 )
1089     *ip |= SOUND_MASK_DIGITAL2;
1090    if ( _mix_settings.sid.digital3 != -1 )
1091     *ip |= SOUND_MASK_DIGITAL3;
1092#endif
1093
1094    return 0;
1095   break;
1096  case SOUND_MIXER_READ_RECMASK:
1097  case SOUND_MIXER_READ_RECSRC:
1098    *ip = SOUND_MASK_VOLUME; // we can currently only read from mixer
1099    return 0;
1100   break;
1101  case SOUND_MIXER_WRITE_RECSRC:
1102    if ( *ip == SOUND_MASK_VOLUME ) {
1103     return  0;
1104    } else {
1105     errno = ENOTSUP;
1106     return -1;
1107    }
1108   break;
1109  case SOUND_MIXER_READ_CAPS:
1110    *ip = 0;
1111    return 0;
1112   break;
1113  case SOUND_MIXER_INFO:
1114    info = vp;
1115    memset(info, 0, sizeof(*info));
1116    strcpy(info->id, "RoarAudio");
1117    strcpy(info->name, "RoarAudio");
1118    return 0;
1119   break;
1120 }
1121
1122 ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p): unknown mixer CTL", handle, req, ip);
1123// _os.ioctl(-1, req, ip);
1124 ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
1125 errno = ENOSYS;
1126 return -1;
1127}
1128
1129// -------------------------------------
1130// buffer size calculation:
1131// -------------------------------------
1132
1133static size_t _get_stream_buffersize (struct handle * handle) {
1134 if ( handle->stream_buffersize )
1135  return handle->stream_buffersize;
1136
1137 return handle->stream_buffersize = handle->stream.info.rate     *
1138                                    handle->stream.info.channels *
1139                                    handle->stream.info.bits     / 800;
1140}
1141
1142// -------------------------------------
1143// emulated functions follow:
1144// -------------------------------------
1145
1146int     open(const char *pathname, int flags, ...) {
1147 int     ret;
1148 mode_t  mode = 0;
1149 va_list args;
1150
1151 _init();
1152
1153 if ( pathname == NULL ) {
1154  errno = EFAULT;
1155  return -1;
1156 }
1157
1158 ROAR_DBG("open(pathname='%s', flags=%x, ...) = ?\n", pathname, flags);
1159 ret = _open_file(pathname, flags);
1160
1161 switch (ret) {
1162  case -2:       // continue as normal, use _op.open()
1163    ROAR_DBG("open(pathname='%s', flags=%x, ...): is not handled by us, pass to kernel\n", pathname, flags);
1164   break;
1165  case -1:       // pass error to caller
1166    return -1;
1167   break;
1168  default:       // return successfully opened pointer to caller
1169    return ret;
1170   break;
1171 }
1172
1173 if (flags & O_CREAT) {
1174  va_start(args, flags);
1175  mode = va_arg(args, _VA_ARGS_MODE_T);
1176  va_end(args);
1177 }
1178
1179 return _os.open(pathname, flags, mode);
1180}
1181
1182int    open64(const char *__file, int __oflag, ...) {
1183 int     ret;
1184 mode_t  mode = 0;
1185 va_list args;
1186
1187 _init();
1188
1189 if ( __file == NULL ) {
1190  errno = EFAULT;
1191  return -1;
1192 }
1193
1194 ROAR_DBG("open64(__file='%s', __oflags=%x, ...) = ?", __file, __oflag);
1195 ret = _open_file(__file, __oflag);
1196
1197 switch (ret) {
1198  case -2:       // continue as normal, use _op.open()
1199    ROAR_DBG("open64(__file='%s', __oflags=%x, ...): not for us, passing to kernel", __file, __oflag);
1200   break;
1201  case -1:       // pass error to caller
1202    return -1;
1203   break;
1204  default:       // return successfully opened pointer to caller
1205    ROAR_DBG("open64(__file='%s', __oflags=%x, ...) = %i", __file, __oflag, ret);
1206    return ret;
1207   break;
1208 }
1209
1210 if (__oflag & O_CREAT) {
1211  va_start(args, __oflag);
1212  mode = va_arg(args, _VA_ARGS_MODE_T);
1213  va_end(args);
1214 }
1215
1216 if ( _os.open64 != NULL ) {
1217  return _os.open64(__file, __oflag, mode);
1218 } else {
1219#ifdef O_LARGEFILE
1220  return _os.open(__file, __oflag | O_LARGEFILE, mode);
1221#else
1222  return _os.open(__file, __oflag, mode);
1223#endif
1224 }
1225}
1226
1227int     close(int fd) {
1228 struct pointer * pointer;
1229 _init();
1230
1231 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
1232  _close_pointer(pointer);
1233  return 0;
1234 }
1235
1236 return _os.close(fd);
1237}
1238
1239ssize_t write(int fd, const void *buf, size_t count) {
1240 struct roar_roardmx_message roardmxmsg;
1241 struct pointer * pointer;
1242 ssize_t ret;
1243 size_t i;
1244
1245 _init();
1246
1247 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
1248  ROAR_DBG("write(fd=%i, buf=%p, count=%lu) = ? // pointer write", fd, buf, (long unsigned int) count);
1249  switch (pointer->handle->type) {
1250   case HT_STREAM: // handle stream specific stuff
1251     if ( pointer->handle->stream_opened == 0 ) {
1252      if ( _open_stream(pointer->handle) == -1 ) {
1253       errno = EIO;
1254       return -1;
1255      }
1256     }
1257   case HT_VIO: // from here we only look at the VIO object of streams, or handle simple VIOs
1258     ret = roar_vio_write(&(pointer->handle->stream_vio), (char*)buf, count);
1259     if ( ret > 0 )
1260      pointer->handle->writec += ret;
1261     return ret;
1262    break;
1263   case HT_DMX: // DMX need specal handling as we need to convert the protocol
1264     if ( pointer->handle->stream_opened == 0 ) {
1265      if ( _open_stream(pointer->handle) == -1 ) {
1266       errno = EIO;
1267       return -1;
1268      }
1269     }
1270     if ( count > 0 ) {
1271      if ( roar_roardmx_message_new_sset(&roardmxmsg) == -1 ) {
1272       errno = EIO;
1273       return -1;
1274      }
1275      for (i = 0; i < count; i++) {
1276       if ( roar_roardmx_message_add_chanval(&roardmxmsg, pointer->handle->pos + i, ((unsigned char*)buf)[i]) == -1 ) {
1277#ifdef EMSGSIZE
1278        errno = EMSGSIZE;
1279#else
1280        errno = EIO;
1281#endif
1282        return -1;
1283       }
1284      }
1285      if ( roar_roardmx_message_send(&roardmxmsg, &(pointer->handle->stream_vio)) == -1 ) {
1286       errno = EIO;
1287       return -1;
1288      }
1289     }
1290     pointer->handle->pos += count;
1291     return count;
1292    break;
1293   default: // we don't know what to do with other types
1294     errno = EINVAL;
1295     return -1;
1296    break;
1297  }
1298 }
1299
1300 return _os.write(fd, buf, count);
1301}
1302
1303ssize_t read(int fd, void *buf, size_t count) {
1304 struct pointer * pointer;
1305 ssize_t ret;
1306
1307 _init();
1308
1309 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
1310  ROAR_DBG("read(fd=%i, buf=%p, count=%lu) = ? // pointer read", fd, buf, (long unsigned int)count);
1311
1312  switch (pointer->handle->type) {
1313   case HT_STREAM:
1314     if ( pointer->handle->stream_opened == 0 ) {
1315      if ( _open_stream(pointer->handle) == -1 ) {
1316       errno = EIO;
1317       return -1;
1318      }
1319     }
1320   case HT_VIO:
1321     ret = roar_vio_read(&(pointer->handle->stream_vio), buf, count);
1322     if ( ret > 0 )
1323      pointer->handle->readc += ret;
1324     return ret;
1325    break;
1326   case HT_STATIC:
1327     ROAR_DBG("read(fd=%i, buf=%p, count=%lu) = ? // type=HT_STATIC", fd, buf, (long unsigned int)count);
1328     ret = pointer->handle->pos + count; // calc the end of the read
1329
1330     if ( ret > (ssize_t)pointer->handle->userdata.sf.len ) {
1331      count = pointer->handle->userdata.sf.len - pointer->handle->pos;
1332     }
1333
1334     memcpy(buf, pointer->handle->userdata.sf.data + pointer->handle->pos, count);
1335     pointer->handle->pos += count;
1336     return count;
1337    break;
1338   default:
1339     errno = EINVAL;
1340     return -1;
1341    break;
1342  }
1343 }
1344
1345 return _os.read(fd, buf, count);
1346}
1347
1348off_t lseek(int fildes, off_t offset, int whence) {
1349 struct pointer * pointer;
1350 ssize_t tmp;
1351
1352 _init();
1353
1354 if ( (pointer = _get_pointer_by_fh(fildes)) != NULL ) {
1355  switch (pointer->handle->type) {
1356   case HT_DMX:
1357     switch (whence) {
1358      case SEEK_SET:
1359        pointer->handle->pos  = offset;
1360       break;
1361      case SEEK_CUR:
1362        pointer->handle->pos += offset;
1363       break;
1364      case SEEK_END:
1365      default:
1366        errno = EINVAL;
1367        return -1;
1368       break;
1369     }
1370     return pointer->handle->pos;
1371    break;
1372   case HT_VIO:
1373     return roar_vio_lseek(&(pointer->handle->stream_vio), offset, whence);
1374    break;
1375   case HT_STATIC:
1376     switch (whence) {
1377      case SEEK_SET:
1378        if ( offset < 0 || offset > (ssize_t)pointer->handle->userdata.sf.len ) {
1379         errno = EINVAL;
1380         return -1;
1381        }
1382        pointer->handle->pos  = offset;
1383       break;
1384      case SEEK_CUR:
1385        tmp = pointer->handle->pos + offset;
1386        if ( tmp < 0 || tmp > (ssize_t)pointer->handle->userdata.sf.len ) {
1387         errno = EINVAL;
1388         return -1;
1389        }
1390        pointer->handle->pos = tmp;
1391       break;
1392      case SEEK_END:
1393        tmp = pointer->handle->userdata.sf.len + offset;
1394        if ( tmp < 0 || tmp > (ssize_t)pointer->handle->userdata.sf.len ) {
1395         errno = EINVAL;
1396         return -1;
1397        }
1398        pointer->handle->pos = tmp;
1399       break;
1400      default:
1401        errno = EINVAL;
1402        return -1;
1403       break;
1404     }
1405    break;
1406   default:
1407     errno = EINVAL;
1408     return -1;
1409    break;
1410  }
1411 }
1412
1413 return _os.lseek(fildes, offset, whence);
1414}
1415
1416IOCTL() {
1417 map_args;
1418 struct pointer * pointer;
1419 struct handle  * handle;
1420 int * ip = NULL;
1421 size_t tmp;
1422 audio_buf_info * bi;
1423 count_info     * ci;
1424#ifdef __FIXME__
1425 char * nosys_reqname = NULL;
1426#endif
1427#ifdef va_argp
1428 va_list args;
1429#endif
1430
1431 _init();
1432
1433 ROAR_DBG("ioctl(__fd=%i, __request=0x%lX) = ?", __fd, (long unsigned int) __request);
1434
1435#ifdef va_argp
1436 va_start (args, ioctl_lastarg);
1437 argp = va_arg (args, void *);
1438 va_end (args);
1439#endif
1440
1441// ROAR_DBG("ioctl(fh=%i, request=%i, ...) = ?", __fd, __request);
1442
1443 ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): argp=%p", __fd, (long unsigned int) __request, argp);
1444
1445 if ( (pointer = _get_pointer_by_fh(__fd)) != NULL ) {
1446  ip = argp;
1447//  ROAR_DBG("ioctl(__fd=%i, __request=0x%lx): ip=%p", __fd, (long unsigned int) __request, ip);
1448#ifdef __FIXME__
1449  switch (__request) {
1450   case SOUND_PCM_READ_RATE: nosys_reqname     = "SOUND_PCM_READ_RATE";     break;
1451   case SOUND_PCM_READ_CHANNELS: nosys_reqname = "SOUND_PCM_READ_CHANNELS"; break;
1452   case SOUND_PCM_READ_BITS: nosys_reqname     = "SOUND_PCM_READ_BITS";     break;
1453   case SOUND_PCM_READ_FILTER: nosys_reqname   = "SOUND_PCM_READ_FILTER";   break;
1454   case SNDCTL_COPR_RESET: nosys_reqname       = "SNDCTL_COPR_RESET";       break;
1455   case SNDCTL_COPR_LOAD: nosys_reqname        = "SNDCTL_COPR_LOAD";        break;
1456   case SNDCTL_COPR_HALT: nosys_reqname        = "SNDCTL_COPR_HALT";        break;
1457   case SNDCTL_COPR_RDATA: nosys_reqname       = "SNDCTL_COPR_RDATA";       break;
1458   case SNDCTL_COPR_RCODE: nosys_reqname       = "SNDCTL_COPR_RCODE";       break;
1459   case SNDCTL_COPR_WDATA: nosys_reqname       = "SNDCTL_COPR_WDATA";       break;
1460   case SNDCTL_COPR_WCODE: nosys_reqname       = "SNDCTL_COPR_WCODE";       break;
1461   case SNDCTL_COPR_RUN: nosys_reqname         = "SNDCTL_COPR_RUN";         break;
1462   case SNDCTL_COPR_SENDMSG: nosys_reqname     = "SNDCTL_COPR_SENDMSG";     break;
1463   case SNDCTL_COPR_RCVMSG: nosys_reqname      = "SNDCTL_COPR_RCVMSG";      break;
1464   case SNDCTL_DSP_GETCAPS: nosys_reqname      = "SNDCTL_DSP_GETCAPS";      break;
1465   default: nosys_reqname = "<<<UNKNOWN>>>"; break;
1466/*
1467   case : nosys_reqname = ""; break;
1468   case : nosys_reqname = ""; break;
1469   case : nosys_reqname = ""; break;
1470*/
1471  }
1472#endif
1473  switch ((handle = pointer->handle)->type) {
1474   case HT_STREAM:
1475     switch (__request) {
1476      case SNDCTL_DSP_RESET:
1477      case SNDCTL_DSP_POST:
1478      case SNDCTL_DSP_SYNC: // ignore for the moment.
1479      case SNDCTL_DSP_SETFRAGMENT: // any fragments should be ok for us...
1480      case SNDCTL_DSP_SETTRIGGER: // we should implement this using PAUSE flag.
1481        return 0;
1482       break;
1483      case SNDCTL_DSP_SPEED:
1484        handle->stream.info.rate = *ip;
1485        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): rate=%i", __fd, (long unsigned int) __request, *ip);
1486        return 0;
1487       break;
1488      case SNDCTL_DSP_CHANNELS:
1489        handle->stream.info.channels = *ip;
1490        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): channels=%i", __fd, (long unsigned int) __request, *ip);
1491        return 0;
1492       break;
1493      case SNDCTL_DSP_STEREO:
1494        handle->stream.info.channels = *ip ? 2 : 1;
1495        return 0;
1496       break;
1497      case SNDCTL_DSP_GETBLKSIZE:
1498        *ip = _get_stream_buffersize(handle);
1499        return 0;
1500       break;
1501      case SNDCTL_DSP_SETFMT:
1502        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): fmt=0x%x", __fd, (long unsigned int) __request, *ip);
1503        return _ioctl_stream_format(handle, *ip);
1504       break;
1505      case SNDCTL_DSP_GETFMTS:
1506//        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): ip=%p", __fd, (long unsigned int) __request, ip);
1507        *ip = _ioctl_stream_format_list();
1508        return 0;
1509       break;
1510      case SNDCTL_DSP_GETOSPACE:
1511      case SNDCTL_DSP_GETISPACE:
1512        bi = argp;
1513        memset(bi, 0, sizeof(*bi));
1514        bi->bytes      = _get_stream_buffersize(handle);
1515        bi->fragments  = 1;
1516        bi->fragsize   = bi->bytes;
1517        bi->fragstotal = 1;
1518        return 0;
1519       break;
1520      case SNDCTL_DSP_GETOPTR:
1521        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): writec=%lu", __fd, (long unsigned int) __request, (long unsigned int) handle->writec);
1522        ci = argp;
1523        memset(ci, 0, sizeof(*ci));
1524        ci->bytes  = handle->writec;
1525        ci->blocks = ci->bytes / (tmp = _get_stream_buffersize(handle));
1526        ci->ptr    = ci->bytes % tmp;
1527        return 0;
1528       break;
1529      case SNDCTL_DSP_GETIPTR:
1530        ci = argp;
1531        memset(ci, 0, sizeof(*ci));
1532        ci->bytes  = handle->readc;
1533        ci->blocks = ci->bytes / (tmp = _get_stream_buffersize(handle));
1534        ci->ptr    = ci->bytes % tmp;
1535        return 0;
1536       break;
1537#ifdef SNDCTL_DSP_GETPLAYVOL
1538      case SNDCTL_DSP_GETPLAYVOL:
1539        return _ioctl_mixer(handle, SOUND_MIXER_READ_PCM, argp);
1540       break;
1541#endif
1542#ifdef SNDCTL_DSP_SETPLAYVOL
1543      case SNDCTL_DSP_SETPLAYVOL:
1544        return _ioctl_mixer(handle, SOUND_MIXER_WRITE_PCM, argp);
1545       break;
1546#endif
1547#ifdef SNDCTL_DSP_NONBLOCK
1548      case SNDCTL_DSP_NONBLOCK:
1549        return fcntl(__fd, F_SETFL, handle->sysio_flags|O_NONBLOCK);
1550       break;
1551#endif
1552      default:
1553#ifdef __FIXME__
1554        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX (%s)) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request, nosys_reqname);
1555#else
1556        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
1557#endif
1558        errno = ENOSYS;
1559        return -1;
1560     }
1561    break;
1562   case HT_MIXER:
1563     return _ioctl_mixer(handle, __request, argp);
1564    break;
1565   default:
1566     ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): unknown handle type: no ioctl()s supported", __fd, (long unsigned int) __request);
1567     ROAR_DBG("ioctl(__fd=%i, __request=0x%lX) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
1568     errno = EINVAL;
1569     return -1;
1570    break;
1571  }
1572 }
1573
1574#ifdef IOCTL_IS_ALIAS
1575 errno = ENOSYS;
1576 return -1;
1577#else
1578 ROAR_DBG("ioctl(__fd=%i, __request=0x%lX, argp=%p): not for us, passing to kernel", __fd, (long unsigned int) __request, argp);
1579 return _os.ioctl(__fd, __request, argp);
1580#endif
1581}
1582
1583int dup(int oldfd) {
1584 struct pointer * pointer;
1585 int ret;
1586
1587 _init();
1588
1589 ret = _os.dup(oldfd);
1590
1591 if (ret == -1)
1592  return -1;
1593
1594 if ( (pointer = _get_pointer_by_fh(oldfd)) != NULL ) {
1595  if ( _attach_pointer(pointer->handle, ret) == NULL ) {
1596   _os.close(ret);
1597   return -1;
1598  }
1599 }
1600
1601 return ret;
1602}
1603
1604int dup2(int oldfd, int newfd) {
1605 struct pointer * pointer;
1606 int ret;
1607
1608 _init();
1609
1610 ret = _os.dup2(oldfd, newfd);
1611
1612 if (ret == -1)
1613  return -1;
1614
1615 if ( (pointer = _get_pointer_by_fh(oldfd)) != NULL ) {
1616  if ( _attach_pointer(pointer->handle, ret) == NULL ) {
1617   _os.close(ret);
1618   return -1;
1619  }
1620 }
1621
1622 return ret;
1623}
1624
1625int select(int nfds, fd_set *readfds, fd_set *writefds,
1626           fd_set *exceptfds, struct timeval *timeout) {
1627 struct roar_vio_selecttv rtv;
1628 struct roar_vio_select * sv  = NULL;
1629 struct pointer * pointer;
1630 struct handle  * handle;
1631 ssize_t ret;
1632 size_t num = 0;
1633 size_t idx;
1634 int i;
1635 int i_r, i_w, i_e;
1636 int max_index = -1;
1637 static volatile int is_critical = 0;
1638
1639 _init();
1640
1641 if ( is_critical )
1642  return _os.select(nfds, readfds, writefds, exceptfds, timeout);
1643
1644 ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = ?", nfds, readfds, writefds, exceptfds, timeout);
1645
1646 if ( nfds == 0 ) {
1647  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = 0", nfds, readfds, writefds, exceptfds, timeout);
1648  return 0;
1649 }
1650
1651 if ( readfds == NULL && writefds == NULL && exceptfds == NULL ) {
1652  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = 0", nfds, readfds, writefds, exceptfds, timeout);
1653  return 0;
1654 }
1655
1656 if ( timeout != NULL ) {
1657  rtv.sec = timeout->tv_sec;
1658  rtv.nsec = timeout->tv_usec*1000;
1659 }
1660
1661 // count number of handles:
1662 for (i = 0; i < nfds; i++) {
1663  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p): i=%i, EXISTS", nfds, readfds, writefds, exceptfds, timeout, i);
1664  if ( (readfds   != NULL && FD_ISSET(i, readfds  )) ||
1665       (writefds  != NULL && FD_ISSET(i, writefds )) ||
1666       (exceptfds != NULL && FD_ISSET(i, exceptfds))
1667     ) {
1668   ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p): i=%i, EXISTS", nfds, readfds, writefds, exceptfds, timeout, i);
1669   num++;
1670   max_index = i;
1671  }
1672 }
1673
1674 if ( num == 0 ) {
1675  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = 0", nfds, readfds, writefds, exceptfds, timeout);
1676  return 0;
1677 }
1678
1679 nfds = max_index + 1;
1680
1681 // create sv;
1682 sv = roar_mm_malloc(sizeof(struct roar_vio_select)*num);
1683 if ( sv == NULL ) {
1684  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = -1", nfds, readfds, writefds, exceptfds, timeout);
1685  return -1;
1686 }
1687
1688 memset(sv, 0, sizeof(struct roar_vio_select)*num);
1689
1690 for (i = 0, idx = 0; i < nfds; i++) {
1691  if ( idx >= num ) {
1692   roar_mm_free(sv);
1693   errno = EFAULT;
1694   ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = -1 // i=%i, idx=%i, num=%i", nfds, readfds, writefds, exceptfds, timeout, i, (int)idx, (int)num);
1695   return -1;
1696  }
1697  i_r = readfds   != NULL && FD_ISSET(i, readfds);
1698  i_w = writefds  != NULL && FD_ISSET(i, writefds);
1699  i_e = exceptfds != NULL && FD_ISSET(i, exceptfds);
1700
1701  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p): i=%i, i_r=%i, i_w=%i, i_e=%i", nfds, readfds, writefds, exceptfds, timeout, i, i_r, i_w, i_e);
1702
1703  if ( i_r || i_w || i_e ) {
1704   // TODO: use VIO for pointers...
1705   if ( (pointer = _get_pointer_by_fh(i)) != NULL ) {
1706    handle = pointer->handle;
1707    sv[idx].vio     = NULL;
1708    sv[idx].fh      = -1;
1709    switch (handle->type) {
1710     case HT_DMX:
1711     case HT_STREAM:
1712       if ( ! handle->stream_opened ) {
1713        // implement this as statichly return OK
1714        errno = ENOSYS;
1715        return -1;
1716       }
1717     case HT_VIO:
1718       sv[idx].vio = &(handle->stream_vio);
1719      break;
1720     default: /* non supported type */
1721       errno = EINVAL;
1722       return -1;
1723      break;
1724    }
1725   } else {
1726    sv[idx].vio     = NULL;
1727    sv[idx].fh      = i;
1728   }
1729
1730   sv[idx].ud.si   = i;
1731   sv[idx].eventsq = (i_r ? ROAR_VIO_SELECT_READ   : 0) |
1732                     (i_w ? ROAR_VIO_SELECT_WRITE  : 0) |
1733                     (i_e ? ROAR_VIO_SELECT_EXCEPT : 0);
1734   idx++;
1735  }
1736 }
1737
1738 is_critical++;
1739 ret = roar_vio_select(sv, num, timeout == NULL ? NULL : &rtv, NULL);
1740 is_critical--;
1741
1742 if ( ret < 1 ) {
1743  roar_mm_free(sv);
1744  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = %i", nfds, readfds, writefds, exceptfds, timeout, (int)ret);
1745  return ret;
1746 }
1747
1748 // update readfds, writefds, exceptfds:
1749 if ( readfds != NULL )
1750  FD_ZERO(readfds);
1751
1752 if ( writefds != NULL )
1753  FD_ZERO(writefds);
1754
1755 if ( exceptfds != NULL )
1756  FD_ZERO(exceptfds);
1757
1758 for (idx = 0; idx < num; idx++) {
1759  if ( sv[idx].eventsa == 0 )
1760   continue;
1761
1762  if ( sv[idx].eventsa & ROAR_VIO_SELECT_READ )
1763   if ( readfds != NULL )
1764    FD_SET(sv[idx].ud.si, readfds);
1765
1766  if ( sv[idx].eventsa & ROAR_VIO_SELECT_WRITE )
1767   if ( writefds != NULL )
1768    FD_SET(sv[idx].ud.si, writefds);
1769
1770  if ( sv[idx].eventsa & ROAR_VIO_SELECT_EXCEPT )
1771   if ( exceptfds != NULL )
1772    FD_SET(sv[idx].ud.si, exceptfds);
1773 }
1774
1775 roar_mm_free(sv);
1776
1777 ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = %i", nfds, readfds, writefds, exceptfds, timeout, (int)ret);
1778 return ret;
1779}
1780
1781int fcntl(int fd, int cmd, ...) {
1782 enum { NONE, UNKNOWN, LONG, POINTER } type = NONE;
1783 struct pointer * pointer;
1784 va_list ap;
1785 long argl = -1;
1786 void * vp = NULL;
1787 int ret   = -1;
1788 int diff;
1789
1790 _init();
1791
1792 ROAR_DBG("fcntl(fd=%i, cmd=%i, ...) = ?", fd, cmd);
1793
1794 switch (cmd) {
1795  case F_DUPFD:
1796  case F_SETFD:
1797  case F_SETFL:
1798  case F_SETOWN:
1799#ifdef F_SETSIG
1800  case F_SETSIG:
1801#endif
1802#ifdef F_SETLEASE
1803  case F_SETLEASE:
1804#endif
1805#ifdef F_NOTIFY
1806  case F_NOTIFY:
1807#endif
1808    type = LONG;
1809   break;
1810  case F_GETFD:
1811  case F_GETFL:
1812  case F_GETOWN:
1813#ifdef F_GETSIG
1814  case F_GETSIG:
1815#endif
1816#ifdef F_GETLEASE
1817  case F_GETLEASE:
1818#endif
1819    type = NONE;
1820   break;
1821  case F_GETLK:
1822  case F_SETLK:
1823  case F_SETLKW:
1824#ifdef F_GETLK64
1825  case F_GETLK64:
1826#endif
1827#ifdef F_SETLK64
1828  case F_SETLK64:
1829#endif
1830#ifdef F_SETLKW64
1831  case F_SETLKW64:
1832#endif
1833    type = POINTER;
1834   break;
1835/*
1836  case F_EXLCK:
1837  case F_GETLK64:
1838  case F_SETLK64:
1839  case F_SETLKW64:
1840  case F_SHLCK:
1841  case F_LINUX_SPECIFIC_BASE:
1842  case F_INPROGRESS:
1843*/
1844  default:
1845    type = UNKNOWN;
1846 }
1847
1848 if ( type == UNKNOWN ) {
1849  ROAR_DBG("fcntl(fd=%i, cmd=%i, ...): unknown data type!", fd, cmd);
1850  ROAR_DBG("fcntl(fd=%i, cmd=%i, ...) = -1 // errno = EINVAL", fd, cmd);
1851  errno = EINVAL;
1852  return -1;
1853 }
1854
1855 if ( type != NONE ) {
1856  va_start(ap, cmd);
1857  switch (type) {
1858   case LONG:
1859     argl = va_arg(ap, long);
1860    break;
1861   case POINTER:
1862     vp = va_arg(ap, void*);
1863    break;
1864   default: /* make compiler happy */
1865    break;
1866  }
1867  va_end(ap);
1868 }
1869
1870 if ( (pointer = _get_pointer_by_fh(fd)) == NULL ) {
1871  switch (type) {
1872   case NONE:
1873     ROAR_DBG("fcntl(fd=%i, cmd=%i): fd is true sysio, pass call to kernel", fd, cmd);
1874     return _os.fcntl(fd, cmd);
1875    break;
1876   case LONG:
1877     ROAR_DBG("fcntl(fd=%i, cmd=%i, arg=%li): fd is true sysio, pass call to kernel", fd, cmd, argl);
1878     return _os.fcntl(fd, cmd, argl);
1879    break;
1880   case POINTER:
1881     ROAR_DBG("fcntl(fd=%i, cmd=%i, lock=%p): fd is true sysio, pass call to kernel", fd, cmd, vp);
1882     return _os.fcntl(fd, cmd, vp);
1883    break;
1884   default: /* make compiler happy */
1885    break;
1886  }
1887 }
1888
1889 ROAR_DBG("fcntl(fd=%i, cmd=%i, ...): fd is true pointer, handle internaly", fd, cmd);
1890
1891 switch (cmd) {
1892  case F_DUPFD:
1893    ret = _os.fcntl(fd, F_DUPFD, argl);
1894
1895    if ( ret != -1 ) {
1896     if ( _attach_pointer(pointer->handle, ret) == NULL ) {
1897      _os.close(ret);
1898      ret = -1;
1899     }
1900    }
1901   break;
1902  case F_SETFD:
1903    if ( argl == 0 ) {
1904     ret = 0;
1905    } else {
1906     errno = ENOSYS;
1907     ret = -1;
1908    }
1909   break;
1910  case F_GETFD:
1911    ret = 0;
1912   break;
1913  case F_GETFL:
1914    ret = pointer->handle->sysio_flags;
1915   break;
1916  case F_SETFL:
1917    diff  = (int)argl ^ pointer->handle->sysio_flags;
1918    diff &= (int)~(int)_O_PARA_DIR;
1919    diff &= (int)~(int)_O_PARA_IGN;
1920
1921    if ( diff & O_NONBLOCK ) {
1922     diff -= O_NONBLOCK;
1923     pointer->handle->sysio_flags ^= O_NONBLOCK;
1924     if ( _update_nonblock(pointer->handle) == -1 ) {
1925      pointer->handle->sysio_flags ^= O_NONBLOCK;
1926      return -1;
1927     }
1928    }
1929
1930    if ( diff == 0 ) { // only flags changed we ignore anyway.
1931     pointer->handle->sysio_flags  = (int)argl;
1932     ret = 0;
1933    } else {
1934     errno = EINVAL;
1935     ret = -1;
1936    }
1937   break;
1938/* TODO: add support for those types:
1939  case F_SETFD:
1940  case F_SETOWN:
1941  case F_SETSIG:
1942  case F_SETLEASE:
1943  case F_NOTIFY:
1944  case F_GETOWN:
1945  case F_GETSIG:
1946  case F_GETLEASE:
1947  case F_GETLK:
1948  case F_SETLK:
1949  case F_SETLKW:
1950*/
1951  default:
1952    errno = ENOSYS;
1953    ret = -1;
1954   break;
1955 }
1956
1957 return ret;
1958}
1959
1960int access(const char *pathname, int mode) {
1961 struct devices * ptr = NULL;
1962
1963 _init();
1964
1965 if ( (ptr = _get_device(pathname)) != NULL ) {
1966  // the only flag we do not support is +x, which means
1967  // we need to reject all requets with X_OK.
1968  if ( mode & X_OK ) {
1969   errno = EACCES;
1970   return -1;
1971  }
1972
1973  // in addition HT_STATIC files do not support write (+w)
1974  // so we need to reject W_OK.
1975  if ( ptr->type == HT_STATIC && (mode & W_OK) ) {
1976   errno = EACCES;
1977   return -1;
1978  }
1979
1980  // Else the access is granted:
1981  return 0;
1982 }
1983
1984 return _os.access(pathname, mode);
1985}
1986
1987int creat(const char *_CREAT_ARG_PATHNAME, mode_t mode) {
1988 _init();
1989
1990 if ( _get_device(_CREAT_ARG_PATHNAME) != NULL ) {
1991  errno = EEXIST;
1992  return -1;
1993 }
1994
1995 return _os.creat(_CREAT_ARG_PATHNAME, mode);
1996}
1997
1998// -------------------------------------
1999// emulated *stat*() functions follow:
2000// -------------------------------------
2001
2002int stat(const char *path, struct stat *buf) {
2003 struct devices * ptr;
2004
2005 _init();
2006
2007 if ( (ptr = _get_device(path)) != NULL ) {
2008  errno = ENOSYS;
2009  return -1;
2010 }
2011
2012 return _os.stat(path, buf);
2013}
2014
2015int fstat(int filedes, struct stat *buf) {
2016 struct pointer * pointer;
2017
2018 _init();
2019
2020 if ( (pointer = _get_pointer_by_fh(filedes)) == NULL ) {
2021  return _os.fstat(filedes, buf);
2022 }
2023
2024 errno = ENOSYS;
2025 return -1;
2026}
2027
2028int lstat(const char *path, struct stat *buf) {
2029 _init();
2030
2031 if ( _get_device(path) != NULL ) {
2032  return stat(path, buf);
2033 }
2034
2035 return _os.lstat(path, buf);
2036}
2037
2038// -------------------------------------
2039// emulated stdio functions follow:
2040// -------------------------------------
2041
2042//roar_vio_to_stdio
2043
2044static int _vio_close    (struct roar_vio_calls * vio) {
2045 int ret = 0;
2046
2047 if ( roar_vio_get_fh(vio) != -1 )
2048  ret = close(roar_vio_get_fh(vio));
2049
2050 roar_mm_free(vio);
2051
2052 return ret;
2053}
2054
2055FILE *fopen(const char *path, const char *mode) {
2056 struct roar_vio_calls * vio;
2057 FILE  * fr;
2058 int     ret;
2059 int     r = 0, w = 0;
2060 int     flags = 0;
2061 int     i;
2062 register char c;
2063
2064 _init();
2065
2066 if ( path == NULL || mode == NULL ) {
2067  errno = EFAULT;
2068  return NULL;
2069 }
2070
2071 ROAR_DBG("open(path='%s', mode='%s') = ?\n", path, mode);
2072
2073 for (i = 0; (c = mode[i]) != 0; i++) {
2074  switch (c) {
2075   case 'r': r = 1; break;
2076   case 'w': w = 1; break;
2077   case 'a': w = 1; break;
2078   case '+':
2079     r = 1;
2080     w = 1;
2081    break;
2082  }
2083 }
2084
2085 if ( r && w ) {
2086  flags = O_RDWR;
2087 } else if ( r ) {
2088  flags = O_RDONLY;
2089 } else if ( w ) {
2090  flags = O_WRONLY;
2091 } else {
2092  errno = EINVAL;
2093  return NULL;
2094 }
2095
2096 ret = _open_file(path, flags);
2097
2098 switch (ret) {
2099  case -2:       // continue as normal, use _op.open()
2100    ROAR_DBG("fopen(path='%s', mode='%s'): not for us, passing to libc", path, mode);
2101   break;
2102  case -1:       // pass error to caller
2103    return NULL;
2104   break;
2105  default:       // return successfully opened pointer to caller
2106#ifdef __USE_FDOPEN__
2107    ROAR_DBG("fopen(path='%s', mode='%s') = fdopen(%i, '%s')", path, mode, ret, mode);
2108    return fdopen(ret, r ? (w ? "rw" : "r") : "w");
2109#else
2110    if ( (vio = roar_mm_malloc(sizeof(struct roar_vio_calls))) == NULL ) {
2111     return NULL; // errno should be set correctly by roar_mm_malloc().
2112    }
2113
2114    roar_vio_init_calls(vio);  // TODO: add error handling.
2115    roar_vio_set_fh(vio, ret); // TODO: add error handling.
2116    vio->close = _vio_close;
2117    if ( (fr = roar_vio_to_stdio(vio, flags)) == NULL ) {
2118     _vio_close(vio);
2119     errno = EIO;
2120     return NULL;
2121    } else {
2122     return fr;
2123    }
2124#endif
2125   break;
2126 }
2127
2128 return _os.fopen(path, mode);
2129}
2130
2131// -------------------------------------
2132// RoarAudio plugin functions follow:
2133// -------------------------------------
2134
2135ROAR_DL_PLUGIN_START(libroaross) {
2136 (void)para;
2137 _init();
2138} ROAR_DL_PLUGIN_END
2139
2140#endif
2141
2142//ll
Note: See TracBrowser for help on using the repository browser.