home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume22
/
ftape
/
part01
/
ftapeipc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-04
|
6KB
|
278 lines
#ifndef lint
static char sccs_id[] = "@(#)2.4 ftapeipc.c 91/09/03 FAST TAPE";
#endif
/*
* Original author: Kari Yli-Kuha, SQ Consulting Ltd.
* Address: Kanslerinkatu 8, 33720 Tampere, Finland
* Phone: (358) 31 165200
*
* Shared memory handling for FAST TAPE
* Uses SysV shared memory and semaphores
*
* Functions:
*
* create_shared() creates shared memory buffer SHBUF and attaches
* global pointer "shbuf" to it.
*
* attach_shared() attaches to an already existing shared memory with "shbuf"
*
* delete_shared() releases shared memory and semaphores
*
* read_cpio() reads cpio(1) stdout from given pipe fd and fills
* shared memory buffers.
*
* write_cpio() reads shared memory buffers and writes to cpio(1) stdin
* thru given pipe fd
*
* semdown() decrements given semaphore (waiting for a buffer)
*
* semdown() increments given semaphore (releasing a buffer)
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include "ftape.h"
struct SHBUF *shbuf; /* shared memory address - GLOBAL */
static int sem_id; /* semaphore id - STATIC */
static int shm_id; /* shared memory id - STATIC */
extern char *shmat();
/*
* create_shared() allocates 'shbufs' SHBUF structures in shared memory.
* Shared memory base address is placed in global variable "shbuf".
*
* Upon successful operation 0 is returned.
* Otherwise -1 is returned and error is written to stderr.
* Reason for failure is normally that SHMMAX is exceeded.
*/
create_shared(key, shm_addr, shbufs)
char *key; /* param to ftok(), normally /dev/tape */
char *shm_addr; /* address to attach to (normally NULL) */
int shbufs; /* # of buffer to allocate */
{
key_t core_key = ftok(key, 0);
if (core_key == -1) {
perror("ftok");
return(-1);
}
/* get semaphores */
sem_id = semget (core_key, NSEMS, 0600 | IPC_CREAT);
if (sem_id < 0) {
perror ("semget");
return (-1);
}
/* get shm */
if ((shm_id = shmget(core_key, shbufs * sizeof(struct SHBUF ),
IPC_CREAT | 0600)) == -1) {
perror ("shmget");
return(-1);
}
/* attach */
if ((shbuf = (struct SHBUF *)shmat(shm_id, (char *) shm_addr, 0))
== (struct SHBUF *) -1) {
perror ("shmat");
return(-1);
}
/* initialize free buffers */
semup (BUFFERS_FREE, shbufs);
return (0);
}
/*
* delete_shared() releases shared memory and semaphores
* sem_id and shm_id are static
*/
delete_shared()
{
/* release semaphores */
if (semctl (sem_id, 0, IPC_RMID, NULL) < 0)
perror ("semctl IPC_RMID");
/* release shared memory */
if (shmctl(shm_id, IPC_RMID, (struct shmid_ds *)0) == -1)
perror ("shmctl IPC_RMID");
return(0);
}
/*
* attach_shared() attaches to an already existing shared memory
* and semaphores. 'key' is used as a parameter to ftok().
*/
attach_shared(key)
char *key;
{
key_t core_key = ftok (key, 0);
if (core_key == -1) {
perror ("ftok");
return(-1);
}
/* get semaphores */
sem_id = semget (core_key, NSEMS, 00600);
if (sem_id < 0) {
perror ("semget");
return (-1);
}
/* get already allocated shared memory */
if ((shm_id = shmget(core_key, 0, IPC_ALLOC | 0600)) == -1) {
perror ("shmget (IPC_ALLOC)");
return(-1);
}
if ((shbuf = (struct SHBUF *)shmat(shm_id, 0, 0)) == (struct SHBUF *) -1) {
perror ("shmat");
return(-1);
}
return (0);
}
/*
* read_cpio
*
* Write to shared memory buffers from the given file descriptor.
*
* Reading is stopped when we get less than SHBUFSIZE bytes.
* The next buffer is marked to contain 0 bytes.
*/
read_cpio(fd, shbufs)
int fd;
int shbufs;
{
int nbuf;
struct SHBUF *buf = shbuf;
nbuf = 0;
do {
semdown (BUFFERS_FREE, 1);
/* check errors while reading tape */
while ((buf->nread = read (fd, buf->buf, SHBUFSIZE*512)) == -1) {
if (errno != EINTR) { /* signal, eg SIGCLD from cpio */
perror ("read");
buf->nread = 0;
return (-1);
}
}
semup (BUFFERS_AVAIL, 1);
if (buf->nread == 0)
break; /* EOF */
buf++; nbuf++;
if (nbuf == shbufs) {
nbuf = 0;
buf = shbuf;
}
} while (1);
/*
* End of file, mark next buffer to contain 0 bytes
* so "ftapewrite" knows to finish.
*/
buf++; nbuf++;
if (nbuf == shbufs) {
nbuf = 0;
buf = shbuf;
}
semdown (BUFFERS_FREE, 1);
buf->nread = 0;
semup (BUFFERS_AVAIL, 1);
return (0);
}
/*
* write_cpio
*
* writes from shared memory buffers to given file descriptor.
*
* Writing is stopped when we get a byffer with 0 bytes in it.
*/
write_cpio(fd, shbufs)
int fd;
int shbufs;
{
int nbuf = 0; /* buffer counter */
struct SHBUF *buf = shbuf;
nbuf = 0;
while (1) {
semdown (BUFFERS_AVAIL, 1);
if (buf->nread == 0) /* end of archive */
break;
write (fd, (char *)buf->buf, buf->nread);
semup (BUFFERS_FREE, 1);
buf++; nbuf++;
if (nbuf == shbufs) {
nbuf = 0;
buf = shbuf;
}
}
(void) close(fd); /* close to flush the pipe */
return (0);
}
/*
* Increment a semaphore
*/
void semup (sem, val)
int sem;
int val;
{
struct sembuf sop;
sop.sem_num = sem;
sop.sem_op = val;
sop.sem_flg = 0;
if (semop (sem_id, &sop, 1) < 0) {
if (errno != EINVAL) {
perror("semop up");
exit(1);
}
}
}
/* Decrement a semaphore */
void semdown (sem, val)
int sem;
int val;
{
struct sembuf sop;
sop.sem_num = sem;
sop.sem_op = -val;
sop.sem_flg = 0;
while (semop (sem_id, &sop, 1) < 0) {
if (errno != EINTR) {
perror ("semop down");
exit (1);
}
}
}