source: golgotha/src/i4/loaders/mp3/xfermem.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 5.7 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9/*
10 *   xfermem.c
11 *
12 *   Oliver Fromme  <oliver.fromme@heim3.tu-clausthal.de>
13 *   Sun Apr  6 02:26:26 MET DST 1997
14 *
15 *   See xfermem.h for documentation/description.
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22#include <errno.h>
23#include <sys/types.h>
24#include <sys/time.h>
25#include <sys/uio.h>
26#include <sys/mman.h>
27#include <sys/socket.h>
28#include <fcntl.h>
29
30#include "xfermem.h"
31
32#ifndef USE_MMAP
33#include <sys/ipc.h>
34#include <sys/shm.h>
35#endif
36
37extern int errno;
38
39#if defined (USE_MMAP) && defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
40#define MAP_ANON MAP_ANONYMOUS
41#endif
42
43void xfermem_init (txfermem **xf, int bufsize, int msize)
44{
45        int regsize = bufsize + msize + sizeof(txfermem);
46
47#ifdef USE_MMAP
48#  ifdef MAP_ANON
49        if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
50                        MAP_ANON | MAP_SHARED, -1, 0)) == (txfermem *) -1) {
51                perror ("mmap()");
52                exit (1);
53        }
54#  else
55        int devzero;
56        if ((devzero = open("/dev/zero", O_RDWR, 0)) == -1) {
57                perror ("open(/dev/zero)");
58                exit (1);
59        }
60        if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
61                        MAP_SHARED, devzero, 0)) == (txfermem *) -1) {
62                perror ("mmap()");
63                exit (1);
64        }
65        close (devzero);
66#  endif
67#else
68        struct shmid_ds shmemds;
69        int shmemid;
70        if ((shmemid = shmget(IPC_PRIVATE, regsize, IPC_CREAT | 0600)) == -1) {
71                perror ("shmget()");
72                exit (1);
73        }
74        if ((*xf = (txfermem *) shmat(shmemid, 0, 0)) == (txfermem *) -1) {
75                perror ("shmat()");
76                shmctl (shmemid, IPC_RMID, &shmemds);
77                exit (1);
78        }
79        if (shmctl(shmemid, IPC_RMID, &shmemds) == -1) {
80                perror ("shmctl()");
81                xfermem_done (*xf);
82                exit (1);
83        }
84#endif
85        if (socketpair(AF_UNIX, SOCK_STREAM, 0, (*xf)->fd) < 0) {
86                perror ("socketpair()");
87                xfermem_done (*xf);
88                exit (1);
89        }
90        (*xf)->freeindex = (*xf)->readindex = 0;
91        (*xf)->wakeme[0] = (*xf)->wakeme[1] = FALSE;
92        (*xf)->data = ((byte *) *xf) + sizeof(txfermem) + msize;
93        (*xf)->metadata = ((byte *) *xf) + sizeof(txfermem);
94        (*xf)->size = bufsize;
95        (*xf)->metasize = msize;
96}
97
98void xfermem_done (txfermem *xf)
99{
100#ifdef USE_MMAP
101        munmap ((caddr_t) xf, xf->size + xf->metasize + sizeof(txfermem));
102#else
103        if (shmdt((void *) xf) == -1) {
104                perror ("shmdt()");
105                exit (1);
106        }
107#endif
108}
109
110void xfermem_init_writer (txfermem *xf)
111{
112        close (xf->fd[XF_READER]);
113}
114
115void xfermem_init_reader (txfermem *xf)
116{
117        close (xf->fd[XF_WRITER]);
118}
119
120int xfermem_get_freespace (txfermem *xf)
121{
122        int freeindex, readindex;
123       
124        if ((freeindex = xf->freeindex) < 0
125                        || (readindex = xf->readindex) < 0)
126                return (0);
127        if (readindex > freeindex)
128                return ((readindex - freeindex) - 1);
129        else
130                return ((xf->size - (freeindex - readindex)) - 1);
131}
132
133int xfermem_get_usedspace (txfermem *xf)
134{
135        int freeindex, readindex;
136
137        if ((freeindex = xf->freeindex) < 0
138                        || (readindex = xf->readindex) < 0)
139                return (0);
140        if (freeindex >= readindex)
141                return (freeindex - readindex);
142        else
143                return (xf->size - (readindex - freeindex));
144}
145
146int xfermem_write (txfermem *xf, byte *data, int count)
147{
148        int nbytes;
149
150        if ((nbytes = xfermem_get_freespace(xf))> count)
151                nbytes = count;
152        if (nbytes) {
153                if (xf->freeindex + nbytes > xf->size) {
154                        int first = xf->size - xf->freeindex;
155                        memcpy (xf->data + xf->freeindex, data, first);
156                        memcpy (xf->data, data + first, nbytes - first);
157                }
158                else
159                        memcpy (xf->data + xf->freeindex, data, nbytes);
160                xf->freeindex = (xf->freeindex + nbytes) % xf->size;
161        }
162        return (nbytes);
163}
164
165int xfermem_read (txfermem *xf, byte *data, int count)
166{
167        int nbytes;
168
169        if ((nbytes = xfermem_get_usedspace(xf))> count)
170                nbytes = count;
171        if (nbytes) {
172                if (xf->readindex + nbytes > xf->size) {
173                        int first = xf->size - xf->readindex;
174                        memcpy (data, xf->data + xf->readindex, first);
175                        memcpy (data + first, xf->data, nbytes - first);
176                }
177                else
178                        memcpy (data, xf->data + xf->readindex, nbytes);
179                xf->readindex = (xf->readindex + nbytes) % xf->size;
180        }
181        return (nbytes);
182}
183
184int xfermem_getcmd (int fd, int block)
185{
186        fd_set selfds;
187        struct timeval selto = {0, 0};
188        byte cmd;
189
190        for (;;) {
191                FD_ZERO (&selfds);
192                FD_SET (fd, &selfds);
193                switch (select(FD_SETSIZE, &selfds, NULL, NULL, block ? NULL : &selto)) {
194                        case 0:
195                                if (!block)
196                                        return (0);
197                                continue;
198                        case -1:
199                                if (errno == EINTR)
200                                        continue;
201                                return (-2);
202                        case 1:
203                                if (FD_ISSET(fd, &selfds))
204                                        switch (read(fd, &cmd, 1)) {
205                                                case 0: /* EOF */
206                                                        return (-1);
207                                                case -1:
208                                                        if (errno == EINTR)
209                                                                continue;
210                                                        return (-3);
211                                                case 1:
212                                                        return (cmd);
213                                                default: /* ?!? */
214                                                        return (-4);
215                                        }
216                                else /* ?!? */
217                                        return (-5);
218                        default: /* ?!? */
219                                return (-6);
220                }
221        }
222}
223
224int xfermem_putcmd (int fd, byte cmd)
225{
226        for (;;)
227                switch (write(fd, &cmd, 1)) {
228                        case 1:
229                                return (1);
230                        case -1:
231                                if (errno != EINTR)
232                                        return (-1);
233                }
234}
235
236int xfermem_block (int readwrite, txfermem *xf)
237{
238        int myfd = xf->fd[readwrite];
239        int result;
240
241        xf->wakeme[readwrite] = TRUE;
242        if (xf->wakeme[1 - readwrite])
243                xfermem_putcmd (myfd, XF_CMD_WAKEUP);
244        result = xfermem_getcmd(myfd, TRUE);
245        xf->wakeme[readwrite] = FALSE;
246        return ((result <= 0) ? -1 : result);
247}
248
249/* EOF */
Note: See TracBrowser for help on using the repository browser.