+++ /dev/null
-/* NOTE: this driver is *deprecated* and should not be used. See the Device API
- * in device-src/ for the new implementation.
- */
-
-#ifdef NO_AMANDA
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/ioctl.h>
-#else
-#include "amanda.h"
-#include "tapeio.h"
-#endif
-
-#include "output-rait.h"
-#include "output-tape.h"
-
-#ifdef NO_AMANDA
-#define amfree(x) do { \
- if (x) { \
- int save_errno = errno; \
- free(x); \
- (x) = NULL; \
- errno = save_errno; \
- }
-} while(0)
-#define tape_open open
-#define tapefd_read read
-#define tapefd_write write
-#define tapefd_close close
-#define tape_access access
-#define tape_stat stat
-#define tapefd_fsf tape_tapefd_fsf
-#define tapefd_rewind tape_tapefd_rewind
-#define tapefd_status tape_tapefd_status
-#define tapefd_unload tape_tapefd_unload
-#define tapefd_weof tape_tapefd_weof
-
-int tapeio_init_devname (char * dev,
- char **dev_left,
- char **dev_right,
- char **dev_next);
-char *tapeio_next_devname (char * dev_left,
- char * dev_right,
- char **dev_next);
-#endif
-
-/*
-** RAIT -- redundant array of (inexpensive?) tapes
-**
-** Author: Marc Mengel <mengel@fnal.gov>
-**
-** This package provides for striping input/output across
-** multiple tape drives.
-**
- Table of Contents
-
- rait.c..................................................1
- MAX_RAITS.........................................2
- rait_table........................................2
- rait_open(char *dev, int flags, mode_t mode)......2
- rait_close(int fd)................................3
- rait_lseek(int fd, long pos, int whence)..........4
- rait_write(int fd, const char *buf, size_t len) ..5
- rait_read(int fd, char *buf, size_t len)..........6
- rait_ioctl(int fd, int op, void *p)...............8
- rait_access(devname, R_OK|W_OK)...................8
- rait_stat(devname, struct statbuf*)...............8
- rait_copy(char *f1, char *f2).....................9
- ifndef NO_AMANDA
- rait_tapefd_fsf(rait_tapefd, count)..........10
- rait_tapefd_rewind(rait_tapefd)..............10
- rait_tapefd_resetofs(rait_tapefd)............10
- rait_tapefd_unload(rait_tapefd)..............10
- rait_tapefd_status(rait_tapefd, stat)........10
- rait_tapefd_weof(rait_tapefd, count).........10
-
- rait.h.................................................1
- typedef RAIT......................................1
- ifdef RAIT_REDIRECT...............................1
- open.........................................1
- close........................................1
- ioctl........................................1
- read.........................................1
- write........................................1
-*/
-
-/*\f*/
-
-/*
-** rait_open takes a string like:
-** "/dev/rmt/tps0d{3,5,7,19}nrnsv"
-** and opens
-** "/dev/rmt/tps0d3nrnsv"
-** "/dev/rmt/tps0d5nrnsv"
-** "/dev/rmt/tps0d7nrnsv"
-** "/dev/rmt/tps0d19nrnsv"
-** as a RAIT.
-**
-** If it has no curly brace, we treat it as a plain device,
-** and do a normal open, and do normal operations on it.
-*/
-
-#ifdef RAIT_DEBUG
-#define rait_debug(...) do { \
- int save_errno = errno; \
- \
- if (0 != getenv("RAIT_DEBUG")) { \
- dbprintf(__VA_ARGS__); \
- } \
- errno = save_errno; \
-} while (0)
-#else
-#define rait_debug(...)
-#endif
-
-static RAIT *rait_table = 0; /* table to keep track of RAITS */
-static size_t rait_table_count;
-
-#ifdef NO_AMANDA
-/*
- * amtable_alloc -- (re)allocate enough space for some number of elements.
- *
- * input: table -- pointer to pointer to table
- * current -- pointer to current number of elements
- * elsize -- size of a table element
- * count -- desired number of elements
- * bump -- round up factor
- * output: table -- possibly adjusted to point to new table area
- * current -- possibly adjusted to new number of elements
- */
-
-static int
-amtable_alloc(
- void ** table,
- int * current,
- size_t elsize,
- int count,
- int bump,
- void * dummy)
-{
- void *table_new;
- int table_count_new;
-
- if (count >= *current) {
- table_count_new = ((count + bump) / bump) * bump;
- table_new = alloc(table_count_new * elsize);
- if (0 != *table) {
- memcpy(table_new, *table, *current * elsize);
- amfree(*table);
- }
- *table = table_new;
- memset(((char *)*table) + *current * elsize,
- 0,
- (table_count_new - *current) * elsize);
- *current = table_count_new;
- }
- return 0;
-}
-
-/*
- * amtable_free -- release a table.
- *
- * input: table -- pointer to pointer to table
- * current -- pointer to current number of elements
- * output: table -- possibly adjusted to point to new table area
- * current -- possibly adjusted to new number of elements
- */
-
-void
-amtable_free(
- void ** table,
- int * current)
-{
- amfree(*table);
- *current = 0;
-}
-#endif
-
-#define rait_table_alloc(fd) amtable_alloc((void **)rait_table_p, \
- &rait_table_count, \
- SIZEOF(*rait_table), \
- (size_t)(fd), \
- 10, \
- NULL)
-
-int
-rait_open(
- char * dev,
- int flags,
- mode_t mask)
-{
- int fd; /* the file descriptor number to return */
- RAIT *res; /* resulting RAIT structure */
- char *dev_left; /* string before { */
- char *dev_right; /* string after } */
- char *dev_next; /* string inside {} */
- char *dev_real; /* parsed device name */
- int rait_flag; /* true if RAIT syntax in dev */
- int save_errno;
- int r;
- RAIT **rait_table_p = &rait_table;
- int **fds_p;
-
- rait_debug(stderr,_("rait_open( %s, %d, %d )\n"), dev, flags, mask);
-
- rait_flag = (0 != strchr(dev, '{'));
-
- if (rait_flag) {
-
- /*
- ** we have to return a valid file descriptor, so use
- ** a dummy one to /dev/null
- */
- fd = open("/dev/null",flags,mask);
- } else {
-
- /*
- ** call the normal tape_open function if we are not
- ** going to do RAIT
- */
- fd = tape_open(dev,flags,mask);
- }
- if(-1 == fd) {
- rait_debug(stderr, _("rait_open:returning %d: %s\n"),
- fd,
- strerror(errno));
- return fd;
- }
-
- if(0 != rait_table_alloc(fd + 1)) {
- save_errno = errno;
- (void)tapefd_close(fd);
- errno = save_errno;
- rait_debug(stderr, _("rait_open:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- res = &rait_table[fd];
-
- memset(res, 0, SIZEOF(*res));
- res->nopen = 1;
-
- res->fd_count = 0;
- if (rait_flag) {
-
- /* copy and parse the dev string so we can scribble on it */
- dev = stralloc(dev);
- if (0 == dev) {
- rait_debug(stderr, _("rait_open:returning %d: %s\n"),
- -1,
- _("out of stralloc memory"));
- return -1;
- }
- if (0 != tapeio_init_devname(dev, &dev_left, &dev_right, &dev_next)) {
- rait_debug(stderr, _("rait_open:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- while (0 != (dev_real = tapeio_next_devname(dev_left, dev_right, &dev_next))) {
- fds_p = &(res->fds);
- r = amtable_alloc((void **)fds_p,
- &res->fd_count,
- SIZEOF(*res->fds),
- (size_t)res->nfds + 1,
- 10,
- NULL);
- if (0 != r) {
- (void)rait_close(fd);
- fd = -1;
- amfree(dev_real);
- break;
- }
- res->fds[ res->nfds ] = tape_open(dev_real,flags,mask);
- rait_debug(stderr,_("rait_open:opening %s yields %d\n"),
- dev_real, res->fds[res->nfds] );
- if ( res->fds[res->nfds] < 0 ) {
- save_errno = errno;
- (void)rait_close(fd);
- amfree(dev_real);
- errno = save_errno;
- fd = -1;
- break;
- }
- tapefd_set_master_fd(res->fds[res->nfds], fd);
- amfree(dev_real);
- res->nfds++;
- }
-
- /* clean up our copied string */
- amfree(dev);
-
- } else {
-
- /*
- ** set things up to treat this as a normal tape if we ever
- ** come in here again
- */
-
- res->nfds = 0;
- fds_p = &(res->fds);
- r = amtable_alloc((void **)fds_p,
- &res->fd_count,
- SIZEOF(*res->fds),
- (size_t)res->nfds + 1,
- 1,
- NULL);
- if (0 != r) {
- (void)tapefd_close(fd);
- memset(res, 0, SIZEOF(*res));
- errno = ENOMEM;
- fd = -1;
- } else {
- res->fds[res->nfds] = fd;
- res->nfds++;
- }
- }
-
- if (fd >= 0 && res->nfds > 0) {
- res->readres = alloc(res->nfds * SIZEOF(*res->readres));
- memset(res->readres, 0, res->nfds * SIZEOF(*res->readres));
- }
-
- rait_debug(stderr, _("rait_open:returning %d%s%s\n"),
- fd,
- (fd < 0) ? ": " : "",
- (fd < 0) ? strerror(errno) : "");
-
- return fd;
-}
-
-#ifdef NO_AMANDA
-int
-tapeio_init_devname(
- char * dev,
- char ** dev_left,
- char ** dev_right,
- char ** dev_next)
-{
- /*
- ** find the first { and then the first } that follows it
- */
- if ( 0 == (*dev_next = strchr(dev, '{'))
- || 0 == (*dev_right = strchr(*dev_next + 1, '}')) ) {
- /* we dont have a {} pair */
- amfree(dev);
- errno = EINVAL;
- return -1;
- }
-
- *dev_left = dev; /* before the { */
- **dev_next = 0; /* zap the { */
- (*dev_next)++;
- (*dev_right)++; /* after the } */
- return 0;
-}
-
-char *
-tapeio_next_devname(
- char * dev_left,
- char * dev_right,
- char ** dev_next)
-{
- char *dev_real = 0;
- char *next;
- int len;
-
- next = *dev_next;
- if (0 != (*dev_next = strchr(next, ','))
- || 0 != (*dev_next = strchr(next, '}'))){
-
- **dev_next = 0; /* zap the terminator */
- (*dev_next)++;
-
- /*
- ** we have one string picked out, build it into the buffer
- */
- len = strlen(dev_left) + strlen(next) + strlen(dev_right) + 1;
- dev_real = alloc(len);
- strcpy(dev_real, dev_left); /* safe */
- strcat(dev_real, next); /* safe */
- strcat(dev_real, dev_right); /* safe */
- }
- return dev_real;
-}
-#endif
-
-/*
-** close everything we opened and free our memory.
-*/
-int
-rait_close(
- int fd)
-{
- int i; /* index into RAIT drives */
- int j; /* individual tapefd_close result */
- int res; /* result from close */
- RAIT *pr; /* RAIT entry from table */
- int save_errno = errno;
- pid_t kid;
- int **fds_p;
-
- rait_debug(stderr,_("rait_close( %d )\n"), fd);
-
- if ((fd < 0) || ((size_t)fd >= rait_table_count)) {
- errno = EBADF;
- rait_debug(stderr, _("rait_close:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- pr = &rait_table[fd];
- if (0 == pr->nopen) {
- errno = EBADF;
- rait_debug(stderr, _("rait_close:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- if (0 == pr->readres && 0 < pr->nfds) {
- pr->readres = alloc(pr->nfds * SIZEOF(*pr->readres));
- memset(pr->readres, 0, pr->nfds * SIZEOF(*pr->readres));
- }
-
- res = 0;
- /*
- ** this looks strange, but we start kids who are going to close the
- ** drives in parallel just after the parent has closed their copy of
- ** the descriptor. ('cause closing tape devices usually causes slow
- ** activities like filemark writes, etc.)
- */
- for( i = 0; i < pr->nfds; i++ ) {
- if(tapefd_can_fork(pr->fds[i])) {
- if ((kid = fork()) == 0) {
- /* we are the child process */
- sleep(0);
- j = tapefd_close(pr->fds[i]);
- exit(j);
- } else {
- /* remember who the child is or that an error happened */
- pr->readres[i] = (ssize_t)kid;
- }
- }
- else {
- j = tapefd_close(pr->fds[i]);
- if ( j != 0 )
- res = j;
- pr->readres[i] = -1;
- }
- }
-
- for( i = 0; i < pr->nfds; i++ ) {
- j = tapefd_close(pr->fds[i]);
- if ( j != 0 )
- res = j;
- }
-
- for( i = 0; i < pr->nfds; i++ ) {
- int stat;
- if(pr->readres[i] != -1) {
- waitpid((pid_t)pr->readres[i], &stat, 0);
- if( WEXITSTATUS(stat) != 0 ) {
- res = WEXITSTATUS(stat);
- if( res == 255 )
- res = -1;
- }
- }
- }
- if (pr->nfds > 1) {
- (void)close(fd); /* close the dummy /dev/null descriptor */
- }
- if (0 != pr->fds) {
- fds_p = &pr->fds;
- amtable_free((void **)fds_p, &pr->fd_count);
- }
- if (0 != pr->readres) {
- amfree(pr->readres);
- }
- if (0 != pr->xorbuf) {
- amfree(pr->xorbuf);
- }
- pr->nopen = 0;
- errno = save_errno;
- rait_debug(stderr, _("rait_close:returning %d%s%s\n"),
- res,
- (res < 0) ? ": " : "",
- (res < 0) ? strerror(errno) : "");
- return res;
-}
-
-/*\f*/
-
-/*
-** seek out to the nth byte on the RAIT set.
-** this is assumed to be evenly divided across all the stripes
-*/
-off_t
-rait_lseek(
- int fd,
- off_t pos,
- int whence)
-{
- int i; /* drive number in RAIT */
- off_t res, /* result of lseeks */
- total; /* total of results */
- RAIT *pr; /* RAIT slot in table */
-
- rait_debug(stderr, _("rait_lseek(%d, %lld, %d)\n"),
- fd, (long long)pos, whence);
-
- if ((fd < 0) || ((size_t)fd >= rait_table_count)) {
- errno = EBADF;
- rait_debug(stderr, _("rait_lseek:returning %d: %s\n"),
- -1,
- strerror(errno));
- return (off_t)-1;
- }
-
- pr = &rait_table[fd];
- if (0 == pr->nopen) {
- errno = EBADF;
- rait_debug(stderr, _("rait_lseek:returning %d: %s\n"),
- -1,
- strerror(errno));
- return (off_t)-1;
- }
-
- if ((pr->nfds > 1) && ((pos % (off_t)(pr->nfds-1)) != (off_t)0)) {
- errno = EDOM;
- total = (off_t)-1;
- } else {
- total = (off_t)0;
- pos = pos / (off_t)pr->nfds;
- for( i = 0; i < pr->nfds; i++ ) {
- if ((off_t)0 >= (res = lseek(pr->fds[i], pos, whence))) {
- total = res;
- break;
- }
- total += res;
- }
- }
- rait_debug(stderr, _("rait_lseek:returning %ld%s%s\n"),
- total,
- (total < 0) ? ": " : "",
- (total < 0) ? strerror(errno) : "");
- return total;
-}
-
-/*\f*/
-
-/*
-** if we only have one stream, just do a write,
-** otherwise compute an xor sum, and do several
-** writes...
-*/
-ssize_t
-rait_write(
- int fd,
- const void *bufptr,
- size_t len)
-{
- const char *buf = bufptr;
- int i; /* drive number */
- size_t j; /* byte offset */
- RAIT *pr; /* RAIT structure for this RAIT */
- ssize_t res;
- ssize_t total = 0;
- int data_fds; /* number of data stream file descriptors */
-
- rait_debug(stderr, _("rait_write(%d,%lx,%d)\n"),fd,(unsigned long)buf,len);
-
- if ((fd < 0) || ((size_t)fd >= rait_table_count)) {
- errno = EBADF;
- rait_debug(stderr, _("rait_write:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- pr = &rait_table[fd];
- if (0 == pr->nopen) {
- errno = EBADF;
- rait_debug(stderr, _("rait_write:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- /* need to be able to slice it up evenly... */
- if (pr->nfds > 1) {
- data_fds = pr->nfds - 1;
- if (0 != len % data_fds) {
- errno = EDOM;
- rait_debug(stderr, _("rait_write:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
- /* each slice gets an even portion */
- len = len / data_fds;
-
- /* make sure we have enough buffer space */
- if (len > (size_t)pr->xorbuflen) {
- if (0 != pr->xorbuf) {
- amfree(pr->xorbuf);
- }
- pr->xorbuf = alloc(len);
- pr->xorbuflen = len;
- }
-
- /* compute the sum */
- memcpy(pr->xorbuf, buf, len);
- for( i = 1; i < data_fds; i++ ) {
- for( j = 0; j < len; j++ ) {
- pr->xorbuf[j] ^= buf[len * i + j];
- }
- }
- } else {
- data_fds = pr->nfds;
- }
-
- /* write the chunks in the main buffer */
- for( i = 0; i < data_fds; i++ ) {
- res = tapefd_write(pr->fds[i], buf + len*i , len);
- rait_debug(stderr, _("rait_write: write(%d,%lx,%d) returns %d%s%s\n"),
- pr->fds[i],
- (unsigned long)(buf + len*i),
- len,
- res,
- (res < 0) ? ": " : "",
- (res < 0) ? strerror(errno) : "");
- if (res < 0) {
- total = res;
- break;
- }
- total += res;
- }
- if (total >= 0 && pr->nfds > 1) {
- /* write the sum, don't include it in the total bytes written */
- res = tapefd_write(pr->fds[i], pr->xorbuf, len);
- rait_debug(stderr, _("rait_write: write(%d,%lx,%d) returns %d%s%s\n"),
- pr->fds[i],
- (unsigned long)pr->xorbuf,
- len,
- res,
- (res < 0) ? ": " : "",
- (res < 0) ? strerror(errno) : "");
- if (res < 0) {
- total = res;
- }
- }
-
- rait_debug(stderr, _("rait_write:returning %d%s%s\n"),
- total,
- (total < 0) ? ": " : "",
- (total < 0) ? strerror(errno) : "");
-
- return total;
-}
-
-/*\f*/
-
-/*
-** once again, if there is one data stream do a read, otherwise
-** do all n reads, and if any of the first n - 1 fail, compute
-** the missing block from the other three, then return the data.
-** there's some silliness here for reading tape with bigger buffers
-** than we wrote with, (thus the extra bcopys down below). On disk if
-** you read with a bigger buffer size than you wrote with, you just
-** garble the data...
-*/
-ssize_t
-rait_read(
- int fd,
- void * bufptr,
- size_t len)
-{
- char *buf = bufptr;
- int nerrors, neofs, errorblock;
- ssize_t total;
- int i;
- size_t j;
- RAIT *pr;
- int data_fds;
- int save_errno = errno;
- ssize_t maxreadres = 0;
- int sum_mismatch = 0;
-
- rait_debug(stderr, _("rait_read(%d,%lx,%d)\n"),fd,(unsigned long)buf,len);
-
- if ((fd < 0) || ((size_t)fd >= rait_table_count)) {
- errno = EBADF;
- rait_debug(stderr, _("rait_read:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- pr = &rait_table[fd];
- if (0 == pr->nopen) {
- errno = EBADF;
- rait_debug(stderr, _("rait_read:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- nerrors = 0;
- neofs = 0;
- errorblock = -1;
- /* once again , we slice it evenly... */
- if (pr->nfds > 1) {
- data_fds = pr->nfds - 1;
- if (0 != len % data_fds) {
- errno = EDOM;
- rait_debug(stderr, _("rait_read:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
- len = len / data_fds;
- } else {
- data_fds = 1;
- }
-
- /* try all the reads, save the result codes */
- /* count the eof/errors */
- for( i = 0; i < data_fds; i++ ) {
- pr->readres[i] = tapefd_read(pr->fds[i], buf + len*i , len);
- rait_debug(stderr, _("rait_read: read on fd %d returns %d%s%s\n"),
- pr->fds[i],
- pr->readres[i],
- (pr->readres[i] < 0) ? ": " : "",
- (pr->readres[i] < 0) ? strerror(errno) : "");
- if ( pr->readres[i] <= 0 ) {
- if ( pr->readres[i] == 0 ) {
- neofs++;
- } else {
- if (0 == nerrors) {
- save_errno = errno;
- }
- nerrors++;
- }
- errorblock = i;
- } else if (pr->readres[i] > maxreadres) {
- maxreadres = pr->readres[i];
- }
- }
- if (pr->nfds > 1) {
- /* make sure we have enough buffer space */
- if (len > (size_t)pr->xorbuflen) {
- if (0 != pr->xorbuf) {
- amfree(pr->xorbuf);
- }
- pr->xorbuf = alloc(len);
- pr->xorbuflen = len;
- }
- pr->readres[i] = tapefd_read(pr->fds[i], pr->xorbuf , len);
- rait_debug(stderr, _("rait_read: read on fd %d returns %d%s%s\n"),
- pr->fds[i],
- pr->readres[i],
- (pr->readres[i] < 0) ? ": " : "",
- (pr->readres[i] < 0) ? strerror(errno) : "");
- }
-
- /*
- * Make sure all the reads were the same length
- */
- for (j = 0; j < (size_t)pr->nfds; j++) {
- if (pr->readres[j] != maxreadres) {
- nerrors++;
- errorblock = (int)j;
- }
- }
-
- /*
- * If no errors, check that the xor sum matches
- */
- if ( nerrors == 0 && pr->nfds > 1 ) {
- for(i = 0; i < (int)maxreadres; i++ ) {
- int sum = 0;
- for(j = 0; (j + 1) < (size_t)pr->nfds; j++) {
- sum ^= (buf + len * j)[i];
- }
- if (sum != pr->xorbuf[i]) {
- sum_mismatch = 1;
- }
- }
- }
-
- /*
- ** now decide what "really" happened --
- ** all n getting eof is a "real" eof
- ** just one getting an error/eof is recoverable if we are doing RAIT
- ** anything else fails
- */
-
- if (neofs == pr->nfds) {
- rait_debug(stderr, _("rait_read:returning 0\n"));
- return 0;
- }
-
- if (sum_mismatch) {
- errno = EDOM;
- rait_debug(stderr, _("rait_read:returning %d: %s\n"),
- -1,
- _("XOR block mismatch"));
- return -1;
- }
-
- if (nerrors > 1 || (pr->nfds <= 1 && nerrors > 0)) {
- errno = save_errno;
- rait_debug(stderr, _("rait_read:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- /*
- ** so now if we failed on a data block, we need to do a recovery
- ** if we failed on the xor block -- who cares?
- */
- if (nerrors == 1 && pr->nfds > 1 && errorblock != pr->nfds-1) {
-
- rait_debug(stderr, _("rait_read: fixing data from fd %d\n"),
- pr->fds[errorblock]);
-
- /* the reads were all *supposed* to be the same size, so... */
- pr->readres[errorblock] = maxreadres;
-
- /* fill it in first with the xor sum */
- memcpy(buf + len * errorblock, pr->xorbuf, len);
-
- /* xor back out the other blocks */
- for( i = 0; i < data_fds; i++ ) {
- if( i != errorblock ) {
- for( j = 0; j < len ; j++ ) {
- buf[j + len * errorblock] ^= buf[j + len * i];
- }
- }
- }
- /* there, now the block is back as if it never failed... */
- }
-
- /* pack together partial reads... */
- total = pr->readres[0];
- for( i = 1; i < data_fds; i++ ) {
- if (total != (ssize_t)(len * i)) {
- memmove(buf + total, buf + len*i, (size_t)pr->readres[i]);
- }
- total += pr->readres[i];
- }
-
- rait_debug(stderr, _("rait_read:returning %d%s%s\n"),
- total,
- (total < 0) ? ": " : "",
- (total < 0) ? strerror(errno) : "");
-
- return total;
-}
-
-/*\f*/
-
-int
-rait_ioctl(
- int fd,
- int op,
- void * p)
-{
- int i, res = 0;
- RAIT *pr;
- int errors = 0;
-
- rait_debug(stderr, _("rait_ioctl(%d,%d)\n"),fd,op);
-
- if ((fd < 0) || ((size_t)fd >= rait_table_count)) {
- errno = EBADF;
- rait_debug(stderr, _("rait_ioctl:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- pr = &rait_table[fd];
- if (0 == pr->nopen) {
- errno = EBADF;
- rait_debug(stderr, _("rait_ioctl:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- for( i = 0; i < pr->nfds ; i++ ) {
- /*@ignore@*/
- res = ioctl(pr->fds[i], op, p);
- /*@end@*/
- if ( res != 0 ) {
- errors++;
- if (errors > 1) {
- break;
- }
- res = 0;
- }
- }
-
- rait_debug(stderr, _("rait_ioctl: returning %d%s%s\n"),
- res,
- (res < 0) ? ": " : "",
- (res < 0) ? strerror(errno) : "");
-
- return res;
-}
-
-/*
-** access() all the devices, returning if any fail
-*/
-int
-rait_access(
- char * devname,
- int flags)
-{
- int res = 0;
- char *dev_left; /* string before { */
- char *dev_right; /* string after } */
- char *dev_next; /* string inside {} */
- char *dev_real; /* parsed device name */
-
- /* copy and parse the dev string so we can scribble on it */
- devname = stralloc(devname);
- if (0 == devname) {
- rait_debug(stderr, _("rait_access:returning %d: %s\n"),
- -1,
- _("out of stralloc memory"));
- return -1;
- }
- if ( 0 != tapeio_init_devname(devname, &dev_left, &dev_right, &dev_next)) {
- rait_debug(stderr, _("rait_access:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- while( 0 != (dev_real = tapeio_next_devname(dev_left, dev_right, &dev_next))) {
- res = tape_access(dev_real, flags);
- rait_debug(stderr,_("rait_access:access( %s, %d ) yields %d\n"),
- dev_real, flags, res );
- amfree(dev_real);
- if (res < 0) {
- break;
- }
- }
- amfree(devname);
-
- rait_debug(stderr, _("rait_access: returning %d%s%s\n"),
- res,
- (res < 0) ? ": " : "",
- (res < 0) ? strerror(errno) : "");
-
- return res;
-}
-
-/*
-** stat all the devices, returning the last one unless one fails
-*/
-int
-rait_stat(
- char * devname,
- struct stat *buf)
-{
- int res = 0;
- char *dev_left; /* string before { */
- char *dev_right; /* string after } */
- char *dev_next; /* string inside {} */
- char *dev_real; /* parsed device name */
-
- /* copy and parse the dev string so we can scribble on it */
- devname = stralloc(devname);
- if (0 == devname) {
- rait_debug(stderr, _("rait_access:returning %d: %s\n"),
- -1,
- _("out of stralloc memory"));
- return -1;
- }
- if ( 0 != tapeio_init_devname(devname, &dev_left, &dev_right, &dev_next)) {
- rait_debug(stderr, _("rait_access:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- while( 0 != (dev_real = tapeio_next_devname(dev_left, dev_right, &dev_next))) {
- res = tape_stat(dev_real, buf);
- rait_debug(stderr,_("rait_stat:stat( %s ) yields %d (%s)\n"),
- dev_real, res, (res != 0) ? strerror(errno) : _("no error") );
- amfree(dev_real);
- if (res != 0) {
- break;
- }
- }
- amfree(devname);
-
- rait_debug(stderr, _("rait_access: returning %d%s%s\n"),
- res,
- (res < 0) ? ": " : "",
- (res < 0) ? strerror(errno) : "");
-
- return res;
-}
-
-/*\f*/
-
-int
-rait_copy(
- char * f1,
- char * f2,
- size_t buflen)
-{
- int t1, t2;
- ssize_t len;
- ssize_t wres;
- char *buf;
- int save_errno;
-
- t1 = rait_open(f1,O_RDONLY,0644);
- if (t1 < 0) {
- return t1;
- }
- t2 = rait_open(f2,O_CREAT|O_RDWR,0644);
- if (t2 < 0) {
- save_errno = errno;
- (void)rait_close(t1);
- errno = save_errno;
- return -1;
- }
- buf = alloc(buflen);
- do {
- len = rait_read(t1,buf,buflen);
- if (len > 0 ) {
- wres = rait_write(t2, buf, (size_t)len);
- if (wres < 0) {
- len = -1;
- break;
- }
- }
- } while( len > 0 );
- save_errno = errno;
- amfree(buf);
- (void)rait_close(t1);
- (void)rait_close(t2);
- errno = save_errno;
- return (len < 0) ? -1 : 0;
-}
-
-/*\f*/
-
-/*
-** Amanda Tape API routines:
-*/
-
-static int
-rait_tapefd_ioctl(
- int (*func0)(int),
- int (*func1)(int, off_t),
- int fd,
- off_t count)
-{
- int i, j, res = 0;
- RAIT *pr;
- int errors = 0;
- pid_t kid;
- int status = 0;
-
- rait_debug(stderr, _("rait_tapefd_ioctl(%d,%d)\n"),fd,count);
-
- if ((fd < 0) || ((size_t)fd >= rait_table_count)) {
- errno = EBADF;
- rait_debug(stderr, _("rait_tapefd_ioctl:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- pr = &rait_table[fd];
- if (0 == pr->nopen) {
- errno = EBADF;
- rait_debug(stderr, _("rait_tapefd_ioctl:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- if (0 == pr->readres && 0 < pr->nfds) {
- pr->readres = alloc(pr->nfds * SIZEOF(*pr->readres));
- memset(pr->readres, 0, pr->nfds * SIZEOF(*pr->readres));
- }
-
- for( i = 0; i < pr->nfds ; i++ ) {
- if(tapefd_can_fork(pr->fds[i])) {
- if ((kid = fork()) < 1) {
- rait_debug(stderr, _("in kid, fork returned %d\n"), kid);
- /* if we are the kid, or fork failed do the action */
- if (func0 != NULL) {
- res = (*func0)(pr->fds[i]);
- } else {
- res = (*func1)(pr->fds[i], count);
- }
- rait_debug(stderr, _("in kid, func (%d) returned %d errno %s\n"),
- pr->fds[i], res, strerror(errno));
- if (kid == 0)
- exit(res);
- } else {
- rait_debug(stderr, _("in parent, fork returned %d\n"), kid);
- pr->readres[i] = (ssize_t)kid;
- }
- }
- else {
- if(func0 != NULL) {
- j = (*func0)(pr->fds[i]);
- } else {
- j = (*func1)(pr->fds[i], count);
- }
- if( j != 0) {
- errors++;
- }
- pr->readres[i] = -1;
- }
- }
- for( i = 0; i < pr->nfds ; i++ ) {
- if(tapefd_can_fork(pr->fds[i])) {
- rait_debug(stderr, _("in parent, waiting for %d\n"), pr->readres[i]);
- waitpid((pid_t)pr->readres[i], &status, 0);
- if( WEXITSTATUS(status) != 0 ) {
- res = WEXITSTATUS(status);
- if( res == 255 )
- res = -1;
- }
- rait_debug(stderr, _("in parent, return code was %d\n"), res);
- if ( res != 0 ) {
- errors++;
- res = 0;
- }
- }
- }
- if (errors > 0) {
- res = -1;
- }
-
- rait_debug(stderr, _("rait_tapefd_ioctl: returning %d%s%s\n"),
- res,
- (res < 0) ? ": " : "",
- (res < 0) ? strerror(errno) : "");
-
- return res;
-}
-
-int
-rait_tapefd_fsf(
- int fd,
- off_t count)
-{
- return rait_tapefd_ioctl(NULL, tapefd_fsf, fd, count);
-}
-
-int
-rait_tapefd_rewind(
- int fd)
-{
- return rait_tapefd_ioctl(tapefd_rewind, NULL, fd, (off_t)-1);
-}
-
-int
-rait_tapefd_unload(
- int fd)
-{
- return rait_tapefd_ioctl(tapefd_unload, NULL, fd, (off_t)-1);
-}
-
-int
-rait_tapefd_weof(
- int fd,
- off_t count)
-{
- return rait_tapefd_ioctl(NULL, tapefd_weof, fd, count);
-}
-
-int
-rait_tape_open(
- char * name,
- int flags,
- mode_t mask)
-{
- return rait_open(name, flags, mask);
-}
-
-int
-rait_tapefd_status(
- int fd,
- struct am_mt_status *stat)
-{
- int i;
- RAIT *pr;
- int res = 0;
- int errors = 0;
-
- rait_debug(stderr, _("rait_tapefd_status(%d)\n"),fd);
-
- if ((fd < 0) || ((size_t)fd >= rait_table_count)) {
- errno = EBADF;
- rait_debug(stderr, _("rait_tapefd_status:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- pr = &rait_table[fd];
- if (0 == pr->nopen) {
- errno = EBADF;
- rait_debug(stderr, _("rait_tapefd_status:returning %d: %s\n"),
- -1,
- strerror(errno));
- return -1;
- }
-
- for( i = 0; i < pr->nfds ; i++ ) {
- res = tapefd_status(pr->fds[i], stat);
- if(res != 0) {
- errors++;
- }
- }
- if (errors > 0) {
- res = -1;
- }
- return res;
-}
-
-void
-rait_tapefd_resetofs(
- int fd)
-{
- (void)rait_lseek(fd, (off_t)0, SEEK_SET);
-}
-
-int
-rait_tapefd_can_fork(
- int fd)
-{
- (void)fd; /* Quiet unused parameter warning */
-
- return 0;
-}
-