pkg://amanda-2.4.5-2.src.rpm:1570510/amanda-2.4.5.tar.gz
info downloads
amanda-2.4.5/ 0000777 0002005 0000313 00000000000 10231512125 006464 5 amanda-2.4.5/tape-src/ 0000777 0002005 0000313 00000000000 10231512126 010203 5 amanda-2.4.5/tape-src/output-tape.h 0000644 0002005 0000313 00000004354 07631740465 012610 /*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: output-tape.h,v 1.1.2.2.2.2 2003/03/06 21:44:21 martinea Exp $
*
* tapeio.c virtual tape interface for normal tape drives.
*/
#ifndef OUTPUT_TAPE_H
#define OUTPUT_TAPE_H
#ifdef NO_AMANDA
#include "output-rait.h"
#else
#include "amanda.h"
#endif
extern int tape_tape_access P((char *, int));
extern int tape_tape_open ();
extern int tape_tape_stat P((char *, struct stat *));
extern int tape_tapefd_close P((int));
extern int tape_tapefd_fsf P((int, int));
extern ssize_t tape_tapefd_read P((int, void *, size_t));
extern int tape_tapefd_rewind P((int));
extern void tape_tapefd_resetofs P((int));
extern int tape_tapefd_unload P((int));
extern int tape_tapefd_status P((int, struct am_mt_status *));
extern int tape_tapefd_weof P((int, int));
extern ssize_t tape_tapefd_write P((int, const void *, size_t));
extern int tape_tapefd_can_fork P((int));
#endif /* OUTPUT_TAPE_H */
amanda-2.4.5/tape-src/output-null.h 0000644 0002005 0000313 00000004260 07631740464 012624 /*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: output-null.h,v 1.1.2.2.2.2 2003/03/06 21:44:20 martinea Exp $
*
* tapeio.c virtual tape interface for a null device.
*/
#ifndef OUTPUT_NULL_H
#define OUTPUT_NULL_H
#include "amanda.h"
extern int null_tape_access P((char *, int));
extern int null_tape_open ();
extern int null_tape_stat P((char *, struct stat *));
extern int null_tapefd_close P((int));
extern int null_tapefd_fsf P((int, int));
extern ssize_t null_tapefd_read P((int, void *, size_t));
extern int null_tapefd_rewind P((int));
extern void null_tapefd_resetofs P((int));
extern int null_tapefd_unload P((int));
extern int null_tapefd_status P((int, struct am_mt_status *));
extern int null_tapefd_weof P((int, int));
extern ssize_t null_tapefd_write P((int, const void *, size_t));
extern int null_tapefd_can_fork P((int));
#endif /* OUTPUT_NULL_H */
amanda-2.4.5/tape-src/output-file.h 0000644 0002005 0000313 00000004260 07631740464 012571 /*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: output-file.h,v 1.1.2.2.2.2 2003/03/06 21:44:20 martinea Exp $
*
* tapeio.c virtual tape interface for a file device.
*/
#ifndef OUTPUT_FILE_H
#define OUTPUT_FILE_H
#include "amanda.h"
extern int file_tape_access P((char *, int));
extern int file_tape_open ();
extern int file_tape_stat P((char *, struct stat *));
extern int file_tapefd_close P((int));
extern int file_tapefd_fsf P((int, int));
extern ssize_t file_tapefd_read P((int, void *, size_t));
extern int file_tapefd_rewind P((int));
extern void file_tapefd_resetofs P((int));
extern int file_tapefd_unload P((int));
extern int file_tapefd_status P((int, struct am_mt_status *));
extern int file_tapefd_weof P((int, int));
extern ssize_t file_tapefd_write P((int, const void *, size_t));
extern int file_tapefd_can_fork P((int));
#endif /* OUTPUT_FILE_H */
amanda-2.4.5/tape-src/Makefile.am 0000644 0002005 0000313 00000003644 07573720625 012206 # Makefile for Amanda tape library.
INCLUDES = -I$(top_srcdir)/common-src
lib_LTLIBRARIES = libamtape.la
LIB_EXTENSION = la
sbin_PROGRAMS= ammt amdd amtapetype
libamtape_la_SOURCES = output-file.c \
output-null.c \
output-rait.c \
output-tape.c \
tapeio.c
libamtape_la_LDFLAGS = -release $(VERSION)
###
# Because libamanda includes routines (e.g. regex) provided by some system
# libraries, and because of the way libtool sets up the command line, we
# need to list libamanda twice here, first to override the system library
# routines, and second to pick up any references in the other libraries.
###
LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
# used for testing only
TEST_PROGS = amtapeio
EXTRA_PROGRAMS = $(TEST_PROGS)
CLEANFILES = *.test.c
amtapetype_SOURCES = tapetype.c
noinst_HEADERS = \
output-file.h \
output-null.h \
output-rait.h \
output-tape.h \
tapeio.h
install-exec-hook:
@list="$(sbin_PROGRAMS) $(sbin_SCRIPTS)"; \
for p in $$list; do \
pa=$(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \
echo chown $(BINARY_OWNER) $$pa; \
chown $(BINARY_OWNER) $$pa; \
echo chgrp $(SETUID_GROUP) $$pa; \
chgrp $(SETUID_GROUP) $$pa; \
done
@list="$(libexec_PROGRAMS) $(libexec_SCRIPTS)"; \
for p in $$list; do \
pa=$(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`; \
echo chown $(BINARY_OWNER) $$pa; \
chown $(BINARY_OWNER) $$pa; \
echo chgrp $(SETUID_GROUP) $$pa; \
chgrp $(SETUID_GROUP) $$pa; \
done
amtapeio_SOURCES = amtapeio.test.c
amtapeio_LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
amtapeio.test.c: $(srcdir)/tapeio.c
echo '#define TEST' >$@
echo '#include "$<"' >>$@
%.test.c: $(srcdir)/%.c
echo '#define TEST' >$@
echo '#include "$<"' >>$@
tapetype:
@echo "Use amtapetype instead"
amanda-2.4.5/tape-src/output-file.c 0000644 0002005 0000313 00000067651 07665465001 012577 /*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: output-file.c,v 1.1.2.4.2.4 2003/05/29 20:13:53 martinea Exp $
*
* tapeio.c virtual tape interface for a file device.
*
* The following was based on testing with real tapes on Solaris 2.6.
* It is possible other OS drivers behave somewhat different in end
* cases, usually involving errors.
*/
#include "amanda.h"
#include "token.h"
#include "tapeio.h"
#include "output-file.h"
#include "fileheader.h"
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
#define MAX_TOKENS 10
#define DATA_INDICATOR "."
#define RECORD_INDICATOR "-"
static
struct volume_info {
char *basename; /* filename from open */
struct file_info *fi; /* file info array */
int fi_limit; /* length of file info array */
int flags; /* open flags */
int mask; /* open mask */
int file_count; /* number of files */
int file_current; /* current file position */
int record_current; /* current record position */
int fd; /* data file descriptor */
int is_online; /* true if "tape" is "online" */
int at_bof; /* true if at begining of file */
int at_eof; /* true if at end of file */
int at_eom; /* true if at end of medium */
int last_operation_write; /* true if last op was a write */
long amount_written; /* KBytes written since open/rewind */
} *volume_info = NULL;
struct file_info {
char *name; /* file name (tapefd_getinfo_...) */
struct record_info *ri; /* record info array */
int ri_count; /* number of record info entries */
int ri_limit; /* length of record info array */
int ri_altered; /* true if record info altered */
};
struct record_info {
int record_size; /* record size */
int start_record; /* first record in range */
int end_record; /* last record in range */
};
static int open_count = 0;
/*
* "Open" the tape by scanning the "data" directory. "Tape files"
* have five leading digits indicating the position (counting from zero)
* followed by a '.' and optional other information (e.g. host/disk/level
* image name).
*
* We allow for the following situations:
*
* + If we see the same "file" (position number) more than once, the
* last one seen wins. This should not normally happen.
*
* + We allow gaps in the positions. This should not normally happen.
*
* Anything in the directory that does not match a "tape file" name
* pattern is ignored.
*
* If the data directory does not exist, the "tape" is considered offline.
* It is allowed to "appear" later.
*/
static int
check_online(fd)
int fd;
{
char *token[MAX_TOKENS];
DIR *tapedir;
struct dirent *entry;
struct file_info *fi;
char *line;
int f;
int pos;
int rc = 0;
/*
* If we are already online, there is nothing else to do.
*/
if (volume_info[fd].is_online) {
goto common_exit;
}
if ((tapedir = opendir(volume_info[fd].basename)) == NULL) {
/*
* We have already opened the info file which is in the same
* directory as the data directory, so ENOENT has to mean the data
* directory is not there, which we treat as being "offline".
* We're already offline at this point (see the above test)
* and this is not an error, so just return success (no error).
*/
rc = (errno != ENOENT);
fprintf(stderr,"ERROR: %s: %s\n", volume_info[fd].basename, strerror(errno));
goto common_exit;
}
while ((entry = readdir(tapedir)) != NULL) {
if (is_dot_or_dotdot(entry->d_name)) {
continue;
}
if (isdigit((int)entry->d_name[0])
&& isdigit((int)entry->d_name[1])
&& isdigit((int)entry->d_name[2])
&& isdigit((int)entry->d_name[3])
&& isdigit((int)entry->d_name[4])
&& entry->d_name[5] == '.') {
/*
* This is a "tape file".
*/
pos = atoi(entry->d_name);
amtable_alloc((void **)&volume_info[fd].fi,
&volume_info[fd].fi_limit,
sizeof(*volume_info[fd].fi),
pos + 1,
10,
NULL);
fi = &volume_info[fd].fi[pos];
if (fi->name != NULL) {
/*
* Two files with the same position???
*/
amfree(fi->name);
fi->ri_count = 0;
}
fi->name = stralloc(&entry->d_name[6]);
if (pos + 1 > volume_info[fd].file_count) {
volume_info[fd].file_count = pos + 1;
}
}
}
closedir(tapedir);
/*
* Parse the info file. We know we are at beginning of file because
* the only thing that can happen to it prior to here is it being
* opened.
*/
for (; (line = areads(fd)) != NULL; free(line)) {
f = split(line, token, sizeof(token) / sizeof(token[0]), " ");
if (f == 2 && strcmp(token[1], "position") == 0) {
volume_info[fd].file_current = atoi(token[2]);
volume_info[fd].record_current = 0;
}
}
/*
* Set EOM and make sure we are not pre-BOI.
*/
if (volume_info[fd].file_current >= volume_info[fd].file_count) {
volume_info[fd].at_eom = 1;
}
if (volume_info[fd].file_current < 0) {
volume_info[fd].file_current = 0;
volume_info[fd].record_current = 0;
}
volume_info[fd].is_online = 1;
common_exit:
return rc;
}
/*
* Open the tape file if not already. If we are beyond the file count
* (end of tape) or the file is missing and we are only reading, set
* up to read /dev/null which will look like EOF. If we are writing,
* create the file.
*/
static int
file_open(fd)
int fd;
{
struct file_info *fi;
char *datafilename = NULL;
char *recordfilename = NULL;
char *f = NULL;
int pos;
char *host;
char *disk;
int level;
char number[NUM_STR_SIZE];
int flags;
int rfd;
int n;
char *line = NULL;
struct record_info *ri;
int start_record;
int end_record;
int record_size;
if (volume_info[fd].fd < 0) {
flags = volume_info[fd].flags;
pos = volume_info[fd].file_current;
amtable_alloc((void **)&volume_info[fd].fi,
&volume_info[fd].fi_limit,
sizeof(*volume_info[fd].fi),
pos + 1,
10,
NULL);
fi = &volume_info[fd].fi[pos];
/*
* See if we are creating a new file.
*/
if (pos >= volume_info[fd].file_count) {
volume_info[fd].file_count = pos + 1;
}
/*
* Generate the file name to open.
*/
if (fi->name == NULL) {
if ((volume_info[fd].flags & 3) != O_RDONLY) {
/*
* This is a new file, so make sure we create/truncate
* it. Generate the name based on the host/disk/level
* information from the caller, if available, else
* a constant.
*/
flags |= (O_CREAT | O_TRUNC);
host = tapefd_getinfo_host(fd);
disk = tapefd_getinfo_disk(fd);
level = tapefd_getinfo_level(fd);
ap_snprintf(number, sizeof(number), "%d", level);
if (host != NULL) {
f = stralloc(host);
}
if (disk != NULL) {
disk = sanitise_filename(disk);
if (f == NULL) {
f = stralloc(disk);
} else {
f = newvstralloc(f, f, ".", disk, NULL);
}
amfree(disk);
}
if (level >= 0) {
if (f == NULL) {
f = stralloc(number);
} else {
f = newvstralloc(f, f, ".", number, NULL);
}
}
if (f == NULL) {
f = stralloc("unknown");
}
amfree(fi->name);
fi->name = stralloc(f);
fi->ri_count = 0;
amfree(f);
} else {
/*
* This is a missing file, so set up to read nothing.
*/
datafilename = stralloc("/dev/null");
recordfilename = stralloc("/dev/null");
}
}
if (datafilename == NULL) {
ap_snprintf(number, sizeof(number), "%05d", pos);
datafilename = vstralloc(volume_info[fd].basename,
number,
DATA_INDICATOR,
volume_info[fd].fi[pos].name,
NULL);
recordfilename = vstralloc(volume_info[fd].basename,
number,
RECORD_INDICATOR,
volume_info[fd].fi[pos].name,
NULL);
}
/*
* Do the data file open.
*/
volume_info[fd].fd = open(datafilename, flags, volume_info[fd].mask);
amfree(datafilename);
/*
* Load the record information.
*/
if (volume_info[fd].fd >= 0
&& fi->ri_count == 0
&& (rfd = open(recordfilename, O_RDONLY)) >= 0) {
for (; (line = areads(rfd)) != NULL; free(line)) {
n = sscanf(line,
"%d %d %d",
&start_record,
&end_record,
&record_size);
if (n == 3) {
amtable_alloc((void **)&fi->ri,
&fi->ri_limit,
sizeof(*fi->ri),
fi->ri_count + 1,
10,
NULL);
ri = &fi->ri[fi->ri_count];
ri->start_record = start_record;
ri->end_record = end_record;
ri->record_size = record_size;
fi->ri_count++;
}
}
aclose(rfd);
}
amfree(recordfilename);
}
return volume_info[fd].fd;
}
/*
* Close the current data file, if open. Dump the record information
* if it has been altered.
*/
static void
file_close(fd)
int fd;
{
struct file_info *fi;
int pos;
char number[NUM_STR_SIZE];
char *filename = NULL;
int r;
FILE *f;
aclose(volume_info[fd].fd);
pos = volume_info[fd].file_current;
amtable_alloc((void **)&volume_info[fd].fi,
&volume_info[fd].fi_limit,
sizeof(*volume_info[fd].fi),
pos + 1,
10,
NULL);
fi = &volume_info[fd].fi[pos];
if (fi->ri_altered) {
ap_snprintf(number, sizeof(number), "%05d", pos);
filename = vstralloc(volume_info[fd].basename,
number,
RECORD_INDICATOR,
fi->name,
NULL);
if ((f = fopen(filename, "w")) == NULL) {
goto common_exit;
}
for (r = 0; r < fi->ri_count; r++) {
fprintf(f,
"%d %d %d\n",
fi->ri[r].start_record,
fi->ri[r].end_record,
fi->ri[r].record_size);
}
afclose(f);
fi->ri_altered = 0;
}
common_exit:
amfree(filename);
}
/*
* Release any files beyond a given position current position and reset
* file_count to file_current to indicate EOM.
*/
static void
file_release(fd)
int fd;
{
int position;
char *filename;
int pos;
char number[NUM_STR_SIZE];
/*
* If the current file is open, release everything beyond it.
* If it is not open, release everything from current.
*/
if (volume_info[fd].fd >= 0) {
position = volume_info[fd].file_current + 1;
} else {
position = volume_info[fd].file_current;
}
for (pos = position; pos < volume_info[fd].file_count; pos++) {
amtable_alloc((void **)&volume_info[fd].fi,
&volume_info[fd].fi_limit,
sizeof(*volume_info[fd].fi),
pos + 1,
10,
NULL);
if (volume_info[fd].fi[pos].name != NULL) {
ap_snprintf(number, sizeof(number), "%05d", pos);
filename = vstralloc(volume_info[fd].basename,
number,
DATA_INDICATOR,
volume_info[fd].fi[pos].name,
NULL);
unlink(filename);
amfree(filename);
filename = vstralloc(volume_info[fd].basename,
number,
RECORD_INDICATOR,
volume_info[fd].fi[pos].name,
NULL);
unlink(filename);
amfree(filename);
amfree(volume_info[fd].fi[pos].name);
volume_info[fd].fi[pos].ri_count = 0;
}
}
volume_info[fd].file_count = position;
}
/*
* Get the size of a particular record. We assume the record information is
* sorted, does not overlap and does not have gaps.
*/
static int
get_record_size(fi, record)
struct file_info *fi;
int record;
{
int r;
struct record_info *ri;
for(r = 0; r < fi->ri_count; r++) {
ri = &fi->ri[r];
if (record <= ri->end_record) {
return ri->record_size;
}
}
/*
* For historical reasons, the default record size is 32 KBytes.
* This allows us to read files written by Amanda with that block
* size before the record information was being kept.
*/
return 32 * 1024;
}
/*
* Update the record information. We assume the record information is
* sorted, does not overlap and does not have gaps.
*/
static void
put_record_size(fi, record, size)
struct file_info *fi;
int record;
int size;
{
int r;
struct record_info *ri;
fi->ri_altered = 1;
if (record == 0) {
fi->ri_count = 0; /* start over */
}
for(r = 0; r < fi->ri_count; r++) {
ri = &fi->ri[r];
if (record - 1 <= ri->end_record) {
/*
* If this record is the same size as the rest of the records
* in this entry, or it would replace the entire entry,
* reset the end record number and size, then zap the chain
* beyond this point.
*/
if (record == ri->start_record || ri->record_size == size) {
ri->end_record = record;
ri->record_size = size;
fi->ri_count = r + 1;
return;
}
/*
* This record needs a new entry right after the current one.
*/
ri->end_record = record - 1;
fi->ri_count = r + 1;
break;
}
}
/*
* Add a new entry.
*/
amtable_alloc((void **)&fi->ri,
&fi->ri_limit,
sizeof(*fi->ri),
fi->ri_count + 1,
10,
NULL);
ri = &fi->ri[fi->ri_count];
ri->start_record = record;
ri->end_record = record;
ri->record_size = size;
fi->ri_count++;
}
/*
* The normal interface routines ...
*/
int
file_tape_open(filename, flags, mask)
char *filename;
int flags;
int mask;
{
int fd = -1;
int save_errno;
char *info_file = NULL;
/*
* Use only O_RDONLY and O_RDWR.
*/
if ((flags & 3) != O_RDONLY) {
flags &= ~3;
flags |= O_RDWR;
}
/*
* If the caller did not set O_CREAT (and thus, pass a mask
* parameter), we may still end up creating data files and need a
* "reasonable" value. Pick a "tight" value on the "better safe
* than sorry" theory.
*/
if ((flags & O_CREAT) == 0) {
mask = 0600;
}
/*
* Open/create the info file for this "tape".
*/
info_file = stralloc2(filename, "/info");
if ((fd = open(info_file, O_RDWR|O_CREAT, 0600)) < 0) {
goto common_exit;
}
/*
* Create the internal info structure for this "tape".
*/
amtable_alloc((void **)&volume_info,
&open_count,
sizeof(*volume_info),
fd + 1,
10,
NULL);
volume_info[fd].flags = flags;
volume_info[fd].mask = mask;
volume_info[fd].file_count = 0;
volume_info[fd].file_current = 0;
volume_info[fd].record_current = 0;
volume_info[fd].fd = -1;
volume_info[fd].is_online = 0; /* true when .../data found */
volume_info[fd].at_bof = 1; /* by definition */
volume_info[fd].at_eof = 0; /* do not know yet */
volume_info[fd].at_eom = 0; /* may get reset below */
volume_info[fd].last_operation_write = 0;
volume_info[fd].amount_written = 0;
/*
* Save the base directory name and see if we are "online".
*/
volume_info[fd].basename = stralloc2(filename, "/data/");
if (check_online(fd)) {
save_errno = errno;
aclose(fd);
fd = -1;
amfree(volume_info[fd].basename);
errno = save_errno;
goto common_exit;
}
common_exit:
amfree(info_file);
/*
* Return the info file descriptor as the unique descriptor for
* this open.
*/
return fd;
}
ssize_t
file_tapefd_read(fd, buffer, count)
int fd;
void *buffer;
size_t count;
{
int result;
int file_fd;
int pos;
int record_size;
int read_size;
/*
* Make sure we are online.
*/
if ((result = check_online(fd)) != 0) {
return result;
}
if (! volume_info[fd].is_online) {
errno = EIO;
return -1;
}
/*
* Do not allow any more reads after we find EOF.
*/
if (volume_info[fd].at_eof) {
errno = EIO;
return -1;
}
/*
* If we are at EOM, set EOF and return a zero length result.
*/
if (volume_info[fd].at_eom) {
volume_info[fd].at_eof = 1;
return 0;
}
/*
* Open the file, if needed.
*/
if ((file_fd = file_open(fd)) < 0) {
return file_fd;
}
/*
* Make sure we do not read too much.
*/
pos = volume_info[fd].file_current;
record_size = get_record_size(&volume_info[fd].fi[pos],
volume_info[fd].record_current);
if (record_size <= count) {
read_size = record_size;
} else {
read_size = count;
}
/*
* Read the data. If we ask for less than the record size, skip to
* the next record boundary.
*/
result = read(file_fd, buffer, read_size);
if (result > 0) {
volume_info[fd].at_bof = 0;
if (result < record_size) {
(void)lseek(file_fd, record_size - result, SEEK_CUR);
}
volume_info[fd].record_current++;
} else if (result == 0) {
volume_info[fd].at_eof = 1;
}
return result;
}
ssize_t
file_tapefd_write(fd, buffer, count)
int fd;
const void *buffer;
size_t count;
{
int file_fd;
int write_count = count;
long length;
long kbytes_left;
int result;
int pos;
/*
* Make sure we are online.
*/
if ((result = check_online(fd)) != 0) {
return result;
}
if (! volume_info[fd].is_online) {
errno = EIO;
return -1;
}
/*
* Check for write access first.
*/
if ((volume_info[fd].flags & 3) == O_RDONLY) {
errno = EBADF;
return -1;
}
/*
* Special case: allow negative buffer size.
*/
if (write_count <= 0) {
return 0; /* special case */
}
/*
* If we are at EOM, it takes precedence over EOF.
*/
if (volume_info[fd].at_eom) {
volume_info[fd].at_eof = 0;
}
#if 0 /*JJ*/
/*
* Writes are only allowed at BOF and EOM.
*/
if (! (volume_info[fd].at_bof || volume_info[fd].at_eom)) {
errno = EIO;
return -1;
}
#endif /*JJ*/
/*
* Writes are only allowed if we are not at EOF.
*/
if (volume_info[fd].at_eof) {
errno = EIO;
return -1;
}
/*
* Open the file, if needed.
*/
if((file_fd = volume_info[fd].fd) < 0) {
file_release(fd);
if ((file_fd = file_open(fd)) < 0) {
return file_fd;
}
}
/*
* Truncate the write if requested and return a simulated ENOSPC.
*/
if ((length = tapefd_getinfo_length(fd)) > 0) {
kbytes_left = length - volume_info[fd].amount_written;
if (write_count / 1024 > kbytes_left) {
write_count = kbytes_left * 1024;
}
}
volume_info[fd].amount_written += (write_count + 1023) / 1024;
if (write_count <= 0) {
volume_info[fd].at_bof = 0;
volume_info[fd].at_eom = 1;
errno = ENOSPC;
return -1;
}
/*
* Do the write and truncate the file, if needed. Checking for
* last_operation_write is an optimization so we only truncate
* once.
*/
if (! volume_info[fd].last_operation_write) {
(void)ftruncate(file_fd, lseek(file_fd, 0, SEEK_CUR));
volume_info[fd].at_bof = 0;
volume_info[fd].at_eom = 1;
}
result = write(file_fd, buffer, write_count);
if (result >= 0) {
volume_info[fd].last_operation_write = 1;
pos = volume_info[fd].file_current;
put_record_size(&volume_info[fd].fi[pos],
volume_info[fd].record_current,
result);
volume_info[fd].record_current++;
}
return result;
}
int
file_tapefd_close(fd)
int fd;
{
int pos;
int save_errno;
char *line;
int len;
char number[NUM_STR_SIZE];
int result;
/*
* If our last operation was a write, write a tapemark.
*/
if (volume_info[fd].last_operation_write) {
if ((result = file_tapefd_weof(fd, 1)) != 0) {
return result;
}
}
/*
* If we are not at BOF, fsf to the next file unless we
* are already at end of tape.
*/
if (! volume_info[fd].at_bof && ! volume_info[fd].at_eom) {
if ((result = file_tapefd_fsf(fd, 1)) != 0) {
return result;
}
}
/*
* Close the file if it is still open.
*/
file_close(fd);
/*
* Release the info structure areas.
*/
for (pos = 0; pos < volume_info[fd].fi_limit; pos++) {
amfree(volume_info[fd].fi[pos].name);
amtable_free((void **)&volume_info[fd].fi[pos].ri,
&volume_info[fd].fi[pos].ri_limit);
volume_info[fd].fi[pos].ri_count = 0;
}
amtable_free((void **)&volume_info[fd].fi, &volume_info[fd].fi_limit);
volume_info[fd].file_count = 0;
amfree(volume_info[fd].basename);
/*
* Update the status file if we were online.
*/
if (volume_info[fd].is_online) {
if (lseek(fd, 0, SEEK_SET) != 0) {
save_errno = errno;
aclose(fd);
errno = save_errno;
return -1;
}
if (ftruncate(fd, 0) != 0) {
save_errno = errno;
aclose(fd);
errno = save_errno;
return -1;
}
ap_snprintf(number, sizeof(number),
"%d", volume_info[fd].file_current);
line = vstralloc("position ", number, "\n", NULL);
len = strlen(line);
result = write(fd, line, len);
amfree(line);
if (result != len) {
if (result >= 0) {
errno = ENOSPC;
}
save_errno = errno;
aclose(fd);
errno = save_errno;
return -1;
}
}
areads_relbuf(fd);
return close(fd);
}
void
file_tapefd_resetofs(fd)
int fd;
{
}
int
file_tapefd_status(fd, stat)
int fd;
struct am_mt_status *stat;
{
int result;
/*
* See if we are online.
*/
if ((result = check_online(fd)) != 0) {
return result;
}
memset((void *)stat, 0, sizeof(*stat));
stat->online_valid = 1;
stat->online = volume_info[fd].is_online;
return 0;
}
int
file_tape_stat(filename, buf)
char *filename;
struct stat *buf;
{
return stat(filename, buf);
}
int
file_tape_access(filename, mode)
char *filename;
int mode;
{
return access(filename, mode);
}
int
file_tapefd_rewind(fd)
int fd;
{
int result = 0;
/*
* Make sure we are online.
*/
if ((result = check_online(fd)) != 0) {
return result;
}
if (! volume_info[fd].is_online) {
errno = EIO;
return -1;
}
/*
* If our last operation was a write, write a tapemark.
*/
if (volume_info[fd].last_operation_write) {
if ((result = file_tapefd_weof(fd, 1)) != 0) {
return result;
}
}
/*
* Close the file if it is still open.
*/
file_close(fd);
/*
* Adjust the position and reset the flags.
*/
volume_info[fd].file_current = 0;
volume_info[fd].record_current = 0;
volume_info[fd].at_bof = 1;
volume_info[fd].at_eof = 0;
volume_info[fd].at_eom
= (volume_info[fd].file_current >= volume_info[fd].file_count);
volume_info[fd].last_operation_write = 0;
volume_info[fd].amount_written = 0;
return result;
}
int
file_tapefd_unload(fd)
int fd;
{
int result;
/*
* Make sure we are online.
*/
if ((result = check_online(fd)) != 0) {
return result;
}
if (! volume_info[fd].is_online) {
errno = EIO;
return -1;
}
file_tapefd_rewind(fd);
return 0;
}
int
file_tapefd_fsf(fd, count)
int fd, count;
{
int result = 0;
/*
* Make sure we are online.
*/
if ((result = check_online(fd)) != 0) {
return result;
}
if (! volume_info[fd].is_online) {
errno = EIO;
return -1;
}
/*
* If our last operation was a write and we are going to move
* backward, write a tapemark.
*/
if (volume_info[fd].last_operation_write && count < 0) {
if ((result = file_tapefd_weof(fd, 1)) != 0) {
errno = EIO;
return -1;
}
}
/*
* Close the file if it is still open.
*/
file_close(fd);
/*
* If we are at EOM and moving backward, adjust the count to go
* one more file.
*/
if (volume_info[fd].at_eom && count < 0) {
count--;
}
/*
* Adjust the position and return an error if we go beyond either
* end of the tape.
*/
volume_info[fd].file_current += count;
if (volume_info[fd].file_current > volume_info[fd].file_count) {
volume_info[fd].file_current = volume_info[fd].file_count;
errno = EIO;
result = -1;
} else if (volume_info[fd].file_current < 0) {
volume_info[fd].file_current = 0;
errno = EIO;
result = -1;
}
volume_info[fd].record_current = 0;
/*
* Set BOF to true so we can write. Set to EOF to false if the
* fsf succeeded or if it failed but we were moving backward (and
* thus we are at beginning of tape), otherwise set it to true so
* a subsequent read will fail. Set EOM to whatever is right.
* Reset amount_written if we ended up back at BOM.
*/
volume_info[fd].at_bof = 1;
if (result == 0 || count < 0) {
volume_info[fd].at_eof = 0;
} else {
volume_info[fd].at_eof = 1;
}
volume_info[fd].at_eom
= (volume_info[fd].file_current >= volume_info[fd].file_count);
volume_info[fd].last_operation_write = 0;
if (volume_info[fd].file_current == 0) {
volume_info[fd].amount_written = 0;
}
return result;
}
int
file_tapefd_weof(fd, count)
int fd, count;
{
int file_fd;
int result = 0;
char *save_host;
char *save_disk;
int save_level;
int save_errno;
/*
* Make sure we are online.
*/
if ((result = check_online(fd)) != 0) {
return result;
}
if (! volume_info[fd].is_online) {
errno = EIO;
return -1;
}
/*
* Check for write access first.
*/
if ((volume_info[fd].flags & 3) == O_RDONLY) {
errno = EACCES;
return -1;
}
/*
* Special case: allow a zero count.
*/
if (count == 0) {
return 0; /* special case */
}
/*
* Disallow negative count.
*/
if (count < 0) {
errno = EINVAL;
return -1;
}
/*
* Close out the current file if open.
*/
if ((file_fd = volume_info[fd].fd) >= 0) {
(void)ftruncate(file_fd, lseek(file_fd, 0, SEEK_CUR));
file_close(fd);
volume_info[fd].file_current++;
volume_info[fd].record_current = 0;
volume_info[fd].at_bof = 1;
volume_info[fd].at_eof = 0;
volume_info[fd].at_eom = 1;
volume_info[fd].last_operation_write = 0;
count--;
}
/*
* Release any data files from current through the end.
*/
file_release(fd);
/*
* Save any labelling information in case we clobber it.
*/
if ((save_host = tapefd_getinfo_host(fd)) != NULL) {
save_host = stralloc(save_host);
}
if ((save_disk = tapefd_getinfo_disk(fd)) != NULL) {
save_disk = stralloc(save_disk);
}
save_level = tapefd_getinfo_level(fd);
/*
* Add more tapemarks.
*/
while (--count >= 0) {
if (file_open(fd) < 0) {
break;
}
file_close(fd);
volume_info[fd].file_current++;
volume_info[fd].file_count = volume_info[fd].file_current;
volume_info[fd].record_current = 0;
volume_info[fd].at_bof = 1;
volume_info[fd].at_eof = 0;
volume_info[fd].at_eom = 1;
volume_info[fd].last_operation_write = 0;
/*
* Only the first "file" terminated by an EOF gets the naming
* information from the caller.
*/
tapefd_setinfo_host(fd, NULL);
tapefd_setinfo_disk(fd, NULL);
tapefd_setinfo_level(fd, -1);
}
/*
* Restore the labelling information.
*/
save_errno = errno;
tapefd_setinfo_host(fd, save_host);
amfree(save_host);
tapefd_setinfo_disk(fd, save_disk);
amfree(save_disk);
tapefd_setinfo_level(fd, save_level);
errno = save_errno;
return result;
}
int
file_tapefd_can_fork(fd)
int fd;
{
return 0;
}
amanda-2.4.5/tape-src/Makefile.in 0000644 0002005 0000313 00000055231 10231511677 012204 # Makefile.in generated by automake 1.8.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Makefile for Amanda tape library.
SOURCES = $(libamtape_la_SOURCES) amdd.c ammt.c $(amtapeio_SOURCES) $(amtapetype_SOURCES)
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_triplet = @host@
sbin_PROGRAMS = ammt$(EXEEXT) amdd$(EXEEXT) amtapetype$(EXEEXT)
EXTRA_PROGRAMS = $(am__EXEEXT_1)
subdir = tape-src
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config/config.h
CONFIG_CLEAN_FILES =
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)"
libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
libamtape_la_LIBADD =
am_libamtape_la_OBJECTS = output-file.lo output-null.lo output-rait.lo \
output-tape.lo tapeio.lo
libamtape_la_OBJECTS = $(am_libamtape_la_OBJECTS)
am__EXEEXT_1 = amtapeio$(EXEEXT)
sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(sbin_PROGRAMS)
amdd_SOURCES = amdd.c
amdd_OBJECTS = amdd.$(OBJEXT)
amdd_LDADD = $(LDADD)
amdd_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
ammt_SOURCES = ammt.c
ammt_OBJECTS = ammt.$(OBJEXT)
ammt_LDADD = $(LDADD)
ammt_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
am_amtapeio_OBJECTS = amtapeio.test.$(OBJEXT)
amtapeio_OBJECTS = $(am_amtapeio_OBJECTS)
amtapeio_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
am_amtapetype_OBJECTS = tapetype.$(OBJEXT)
amtapetype_OBJECTS = $(am_amtapetype_OBJECTS)
amtapetype_LDADD = $(LDADD)
amtapetype_DEPENDENCIES = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/amdd.Po ./$(DEPDIR)/ammt.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/amtapeio.test.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/output-file.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/output-null.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/output-rait.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/output-tape.Plo ./$(DEPDIR)/tapeio.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/tapetype.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libamtape_la_SOURCES) amdd.c ammt.c $(amtapeio_SOURCES) \
$(amtapetype_SOURCES)
DIST_SOURCES = $(libamtape_la_SOURCES) amdd.c ammt.c \
$(amtapeio_SOURCES) $(amtapetype_SOURCES)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMANDA_DBGDIR = @AMANDA_DBGDIR@
AMANDA_DEBUG_DAYS = @AMANDA_DEBUG_DAYS@
AMANDA_TMPDIR = @AMANDA_TMPDIR@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMPLOT_CAT_COMPRESS = @AMPLOT_CAT_COMPRESS@
AMPLOT_CAT_GZIP = @AMPLOT_CAT_GZIP@
AMPLOT_CAT_PACK = @AMPLOT_CAT_PACK@
AMPLOT_COMPRESS = @AMPLOT_COMPRESS@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
AWK_VAR_ASSIGNMENT_OPT = @AWK_VAR_ASSIGNMENT_OPT@
BINARY_OWNER = @BINARY_OWNER@
CAT = @CAT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CHIO = @CHIO@
CHS = @CHS@
CLIENT_LOGIN = @CLIENT_LOGIN@
CLIENT_SCRIPTS_OPT = @CLIENT_SCRIPTS_OPT@
COMPRESS = @COMPRESS@
CONFIGURE_COMMAND = @CONFIGURE_COMMAND@
CONFIG_DIR = @CONFIG_DIR@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DB_EXT = @DB_EXT@
DD = @DD@
DEFAULT_CHANGER_DEVICE = @DEFAULT_CHANGER_DEVICE@
DEFAULT_CONFIG = @DEFAULT_CONFIG@
DEFAULT_RAW_TAPE_DEVICE = @DEFAULT_RAW_TAPE_DEVICE@
DEFAULT_SERVER = @DEFAULT_SERVER@
DEFAULT_TAPE_DEVICE = @DEFAULT_TAPE_DEVICE@
DEFAULT_TAPE_SERVER = @DEFAULT_TAPE_SERVER@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DUMP = @DUMP@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
GETCONF = @GETCONF@
GNUPLOT = @GNUPLOT@
GNUTAR = @GNUTAR@
GNUTAR_LISTED_INCREMENTAL_DIRX = @GNUTAR_LISTED_INCREMENTAL_DIRX@
GREP = @GREP@
GZIP = @GZIP@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LN_S = @LN_S@
LTALLOCA = @LTALLOCA@
LTLIBOBJS = @LTLIBOBJS@
MAILER = @MAILER@
MAKEINFO = @MAKEINFO@
MAXTAPEBLOCKSIZE = @MAXTAPEBLOCKSIZE@
MCUTIL = @MCUTIL@
MT = @MT@
MTX = @MTX@
MT_FILE_FLAG = @MT_FILE_FLAG@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PCAT = @PCAT@
PERL = @PERL@
PRINT = @PRINT@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@
RESTORE = @RESTORE@
SAMBA_CLIENT = @SAMBA_CLIENT@
SERVICE_SUFFIX = @SERVICE_SUFFIX@
SETUID_GROUP = @SETUID_GROUP@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SNAPSHOT_STAMP = @SNAPSHOT_STAMP@
STRIP = @STRIP@
USE_VERSION_SUFFIXES = @USE_VERSION_SUFFIXES@
VDUMP = @VDUMP@
VERSION = @VERSION@
VERSION_COMMENT = @VERSION_COMMENT@
VERSION_MAJOR = @VERSION_MAJOR@
VERSION_MINOR = @VERSION_MINOR@
VERSION_PATCH = @VERSION_PATCH@
VERSION_SUFFIX = @VERSION_SUFFIX@
VRESTORE = @VRESTORE@
VXDUMP = @VXDUMP@
VXRESTORE = @VXRESTORE@
WANT_AMPLOT_FALSE = @WANT_AMPLOT_FALSE@
WANT_AMPLOT_TRUE = @WANT_AMPLOT_TRUE@
WANT_CHG_SCSI_FALSE = @WANT_CHG_SCSI_FALSE@
WANT_CHG_SCSI_TRUE = @WANT_CHG_SCSI_TRUE@
WANT_CHIO_SCSI_FALSE = @WANT_CHIO_SCSI_FALSE@
WANT_CHIO_SCSI_TRUE = @WANT_CHIO_SCSI_TRUE@
WANT_CLIENT_FALSE = @WANT_CLIENT_FALSE@
WANT_CLIENT_TRUE = @WANT_CLIENT_TRUE@
WANT_RECOVER_FALSE = @WANT_RECOVER_FALSE@
WANT_RECOVER_TRUE = @WANT_RECOVER_TRUE@
WANT_RESTORE_FALSE = @WANT_RESTORE_FALSE@
WANT_RESTORE_TRUE = @WANT_RESTORE_TRUE@
WANT_RUNTIME_PSEUDO_RELOC_FALSE = @WANT_RUNTIME_PSEUDO_RELOC_FALSE@
WANT_RUNTIME_PSEUDO_RELOC_TRUE = @WANT_RUNTIME_PSEUDO_RELOC_TRUE@
WANT_SAMBA_FALSE = @WANT_SAMBA_FALSE@
WANT_SAMBA_TRUE = @WANT_SAMBA_TRUE@
WANT_SERVER_FALSE = @WANT_SERVER_FALSE@
WANT_SERVER_TRUE = @WANT_SERVER_TRUE@
WANT_SETUID_CLIENT_FALSE = @WANT_SETUID_CLIENT_FALSE@
WANT_SETUID_CLIENT_TRUE = @WANT_SETUID_CLIENT_TRUE@
WANT_TAPE_FALSE = @WANT_TAPE_FALSE@
WANT_TAPE_TRUE = @WANT_TAPE_TRUE@
XFSDUMP = @XFSDUMP@
XFSRESTORE = @XFSRESTORE@
YACC = @YACC@
ac_c = @ac_c@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_n = @ac_n@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
INCLUDES = -I$(top_srcdir)/common-src
lib_LTLIBRARIES = libamtape.la
LIB_EXTENSION = la
libamtape_la_SOURCES = output-file.c \
output-null.c \
output-rait.c \
output-tape.c \
tapeio.c
libamtape_la_LDFLAGS = -release $(VERSION)
###
# Because libamanda includes routines (e.g. regex) provided by some system
# libraries, and because of the way libtool sets up the command line, we
# need to list libamanda twice here, first to override the system library
# routines, and second to pick up any references in the other libraries.
###
LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
# used for testing only
TEST_PROGS = amtapeio
CLEANFILES = *.test.c
amtapetype_SOURCES = tapetype.c
noinst_HEADERS = \
output-file.h \
output-null.h \
output-rait.h \
output-tape.h \
tapeio.h
amtapeio_SOURCES = amtapeio.test.c
amtapeio_LDADD = ../common-src/libamanda.$(LIB_EXTENSION) \
libamtape.$(LIB_EXTENSION) \
../common-src/libamanda.$(LIB_EXTENSION)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tape-src/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu tape-src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
else :; fi; \
done
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
p="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
$(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" = "$$p" && dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libamtape.la: $(libamtape_la_OBJECTS) $(libamtape_la_DEPENDENCIES)
$(LINK) -rpath $(libdir) $(libamtape_la_LDFLAGS) $(libamtape_la_OBJECTS) $(libamtape_la_LIBADD) $(LIBS)
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(sbindir)" || $(mkdir_p) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
|| test -f $$p1 \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
else :; fi; \
done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(sbin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
rm -f "$(DESTDIR)$(sbindir)/$$f"; \
done
clean-sbinPROGRAMS:
@list='$(sbin_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
amdd$(EXEEXT): $(amdd_OBJECTS) $(amdd_DEPENDENCIES)
@rm -f amdd$(EXEEXT)
$(LINK) $(amdd_LDFLAGS) $(amdd_OBJECTS) $(amdd_LDADD) $(LIBS)
ammt$(EXEEXT): $(ammt_OBJECTS) $(ammt_DEPENDENCIES)
@rm -f ammt$(EXEEXT)
$(LINK) $(ammt_LDFLAGS) $(ammt_OBJECTS) $(ammt_LDADD) $(LIBS)
amtapeio$(EXEEXT): $(amtapeio_OBJECTS) $(amtapeio_DEPENDENCIES)
@rm -f amtapeio$(EXEEXT)
$(LINK) $(amtapeio_LDFLAGS) $(amtapeio_OBJECTS) $(amtapeio_LDADD) $(LIBS)
amtapetype$(EXEEXT): $(amtapetype_OBJECTS) $(amtapetype_DEPENDENCIES)
@rm -f amtapetype$(EXEEXT)
$(LINK) $(amtapetype_LDFLAGS) $(amtapetype_OBJECTS) $(amtapetype_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amdd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ammt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amtapeio.test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output-file.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output-null.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output-rait.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output-tape.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapeio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapetype.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -z "$$unique" && unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
clean-sbinPROGRAMS mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-exec-am: install-libLTLIBRARIES install-sbinPROGRAMS
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
uninstall-sbinPROGRAMS
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libLTLIBRARIES clean-libtool clean-sbinPROGRAMS ctags \
distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-libLTLIBRARIES install-man \
install-sbinPROGRAMS install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-info-am \
uninstall-libLTLIBRARIES uninstall-sbinPROGRAMS
install-exec-hook:
@list="$(sbin_PROGRAMS) $(sbin_SCRIPTS)"; \
for p in $$list; do \
pa=$(DESTDIR)$(sbindir)/`echo $$p|sed '$(transform)'`; \
echo chown $(BINARY_OWNER) $$pa; \
chown $(BINARY_OWNER) $$pa; \
echo chgrp $(SETUID_GROUP) $$pa; \
chgrp $(SETUID_GROUP) $$pa; \
done
@list="$(libexec_PROGRAMS) $(libexec_SCRIPTS)"; \
for p in $$list; do \
pa=$(DESTDIR)$(libexecdir)/`echo $$p|sed '$(transform)'`; \
echo chown $(BINARY_OWNER) $$pa; \
chown $(BINARY_OWNER) $$pa; \
echo chgrp $(SETUID_GROUP) $$pa; \
chgrp $(SETUID_GROUP) $$pa; \
done
amtapeio.test.c: $(srcdir)/tapeio.c
echo '#define TEST' >$@
echo '#include "$<"' >>$@
%.test.c: $(srcdir)/%.c
echo '#define TEST' >$@
echo '#include "$<"' >>$@
tapetype:
@echo "Use amtapetype instead"
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
amanda-2.4.5/tape-src/output-rait.h 0000644 0002005 0000313 00000006751 07631740465 012621 #ifndef RAIT_H
#define RAIT_H
typedef struct {
int nopen;
int nfds;
int fd_count;
int *fds;
int *readres;
int xorbuflen;
char *xorbuf;
} RAIT;
#ifdef NO_AMANDA
#define stralloc strdup
#define P(x) x /* for function prototypes */
/*
* Tape drive status structure. This abstracts the things we are
* interested in from the free-for-all of what the various drivers
* supply.
*/
struct am_mt_status {
char online_valid; /* is the online flag valid? */
char bot_valid; /* is the BOT flag valid? */
char eot_valid; /* is the EOT flag valid? */
char protected_valid; /* is the protected flag valid? */
char flags_valid; /* is the flags field valid? */
char fileno_valid; /* is the fileno field valid? */
char blkno_valid; /* is the blkno field valid? */
char device_status_valid; /* is the device status field valid? */
char error_status_valid; /* is the device status field valid? */
char online; /* true if device is online/ready */
char bot; /* true if tape is at the beginning */
char eot; /* true if tape is at end of medium */
char protected; /* true if tape is write protected */
long flags; /* device flags, whatever that is */
long fileno; /* tape file number */
long blkno; /* block within file */
int device_status_size; /* size of orig device status field */
unsigned long device_status; /* "device status", whatever that is */
int error_status_size; /* size of orig error status field */
unsigned long error_status; /* "error status", whatever that is */
};
#endif
extern int rait_open ();
extern int rait_access P((char *, int));
extern int rait_stat P((char *, struct stat *));
extern int rait_close P((int ));
extern int rait_lseek P((int , long, int));
extern ssize_t rait_write P((int , const void *, size_t));
extern ssize_t rait_read P((int , void *, size_t));
extern int rait_ioctl P((int , int, void *));
extern int rait_copy P((char *f1, char *f2, int buflen));
extern char *rait_init_namelist P((char * dev,
char **dev_left,
char **dev_right,
char **dev_next));
extern int rait_next_name P((char * dev_left,
char * dev_right,
char **dev_next,
char * dev_real));
extern int rait_tape_open ();
extern int rait_tapefd_fsf P((int rait_tapefd, int count));
extern int rait_tapefd_rewind P((int rait_tapefd));
extern void rait_tapefd_resetofs P((int rait_tapefd));
extern int rait_tapefd_unload P((int rait_tapefd));
extern int rait_tapefd_status P((int rait_tapefd, struct am_mt_status *stat));
extern int rait_tapefd_weof P((int rait_tapefd, int count));
extern int rait_tapefd_can_fork P((int));
#ifdef RAIT_REDIRECT
/* handle ugly Solaris stat mess */
#ifdef _FILE_OFFSET_BITS
#include <sys/stat.h>
#undef stat
#undef open
#if _FILE_OFFSET_BITS == 64
struct stat {
dev_t st_dev;
long st_pad1[3]; /* reserved for network id */
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
long st_pad2[2];
off_t st_size;
timestruc_t st_atim;
timestruc_t st_mtim;
timestruc_t st_ctim;
long st_blksize;
blkcnt_t st_blocks;
char st_fstype[_ST_FSTYPSZ];
long st_pad4[8]; /* expansion area */
};
#endif
#endif
#define access(p,f) rait_access(p,f)
#define stat(a,b) rait_stat(a,b)
#define open rait_open
#define close(a) rait_close(a)
#define read(f,b,l) rait_read(f,b,l)
#define write(f,b,l) rait_write(f,b,l)
#define ioctl(f,n,x) rait_ioctl(f,n,x)
#endif
#endif
amanda-2.4.5/tape-src/output-rait.c 0000644 0002005 0000313 00000070660 10043223626 012576 #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 { \
int save_errno = errno; \
free(x); \
(x) = 0; \
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, int mode).........2
rait_close(int fd)................................3
rait_lseek(int fd, long pos, int whence)..........4
rait_write(int fd, const char *buf, int len) .....5
rait_read(int fd, char *buf, int 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
*/
/**/
/*
** 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(p) do { \
int save_errno = errno; \
\
if (0!=getenv("RAIT_DEBUG")) { \
fprintf p; \
} \
errno = save_errno; \
} while (0)
#else
#define rait_debug(p)
#endif
static RAIT *rait_table = 0; /* table to keep track of RAITS */
static int 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 = malloc(table_count_new * elsize);
if (0 == table_new) {
errno = ENOMEM;
return -1;
}
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(table, current)
void **table;
int *current;
{
amfree(*table);
*current = 0;
}
#endif
#define rait_table_alloc(fd) amtable_alloc((void **)&rait_table, \
&rait_table_count, \
sizeof(*rait_table), \
(fd), \
10, \
NULL)
int
rait_open(char *dev, int flags, int 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_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))) {
r = amtable_alloc((void **)&res->fds,
&res->fd_count,
sizeof(*res->fds),
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;
r = amtable_alloc((void **)&res->fds,
&res->fd_count,
sizeof(*res->fds),
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 = (int *) malloc(res->nfds * sizeof(*res->readres));
if (0 == res->readres) {
(void)rait_close(fd);
errno = ENOMEM;
fd = -1;
} else {
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;
if ( 0 != (dev_real = malloc(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;
int kid;
rait_debug((stderr,"rait_close( %d )\n", fd));
if (fd < 0 || 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 = (int *) malloc(pr->nfds * sizeof(*pr->readres));
if (0 == pr->readres) {
errno = ENOMEM;
rait_debug((stderr, "rait_close:returning %d: %s\n",
-1,
strerror(errno)));
return -1;
}
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] = 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( 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) {
amtable_free((void **)&pr->fds, &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;
}
/**/
/*
** seek out to the nth byte on the RAIT set.
** this is assumed to be evenly divided across all the stripes
*/
int
rait_lseek(int fd, long pos, int whence) {
int i; /* drive number in RAIT */
long res, /* result of lseeks */
total; /* total of results */
RAIT *pr; /* RAIT slot in table */
rait_debug((stderr, "rait_lseek(%d,%ld,%d)\n",fd,pos,whence));
if (fd < 0 || fd >= rait_table_count) {
errno = EBADF;
rait_debug((stderr, "rait_lseek:returning %d: %s\n",
-1,
strerror(errno)));
return -1;
}
pr = &rait_table[fd];
if (0 == pr->nopen) {
errno = EBADF;
rait_debug((stderr, "rait_lseek:returning %d: %s\n",
-1,
strerror(errno)));
return -1;
}
if (pr->nfds > 1 && (pos % (pr->nfds-1)) != 0) {
errno = EDOM;
total = -1;
} else {
total = 0;
pos = pos / pr->nfds;
for( i = 0; i < pr->nfds; i++ ) {
if (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;
}
/**/
/*
** 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 = 0, j; /* drive number, byte offset */
RAIT *pr; /* RAIT structure for this RAIT */
int res, 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 || 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 > pr->xorbuflen) {
if (0 != pr->xorbuf) {
amfree(pr->xorbuf);
}
pr->xorbuf = malloc(len);
if (0 == pr->xorbuf) {
errno = ENOMEM;
rait_debug((stderr, "rait_write:returning %d: %s\n",
-1,
strerror(errno)));
return -1;
}
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 */
if (total >= 0) {
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;
}
/**/
/*
** 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,
total,
errorblock;
int i,j;
RAIT *pr;
int data_fds;
int save_errno = errno;
int maxreadres = 0;
int sum_mismatch = 0;
rait_debug((stderr, "rait_read(%d,%lx,%d)\n",fd,(unsigned long)buf,len));
if (fd < 0 || 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;
total = 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 > pr->xorbuflen) {
if (0 != pr->xorbuf) {
amfree(pr->xorbuf);
}
pr->xorbuf = malloc(len);
if (0 == pr->xorbuf) {
errno = ENOMEM;
rait_debug((stderr, "rait_write:returning %d: %s\n",
-1,
strerror(errno)));
return -1;
}
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 < pr->nfds; j++) {
if (pr->readres[j] != maxreadres) {
nerrors++;
errorblock = j;
}
}
/*
* If no errors, check that the xor sum matches
*/
if ( nerrors == 0 && pr->nfds > 1 ) {
for(i = 0; i < maxreadres; i++ ) {
int sum = 0;
for(j = 0; j < pr->nfds - 1; 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 != len * i) {
memmove(buf + total, buf + len*i, 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;
}
/**/
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 || 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++ ) {
res = ioctl(pr->fds[i], op, p);
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;
}
/**/
int rait_copy(char *f1, char *f2, int buflen) {
int t1, t2;
int len, 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 = malloc(buflen);
if (0 == buf) {
(void)rait_close(t1);
(void)rait_close(t2);
errno = ENOMEM;
return -1;
}
do {
len = rait_read(t1,buf,buflen);
if (len > 0 ) {
wres = rait_write(t2, buf, 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;
}
/**/
/*
** Amanda Tape API routines:
*/
static int rait_tapefd_ioctl(int (*func0)(int),
int (*func1)(int, int),
int fd,
int count) {
int i, j, res = 0;
RAIT *pr;
int errors = 0;
int kid;
int stat;
rait_debug((stderr, "rait_tapefd_ioctl(%d,%d)\n",fd,count));
if (fd < 0 || 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 = (int *) malloc(pr->nfds * sizeof(*pr->readres));
if (0 == pr->readres) {
errno = ENOMEM;
rait_debug((stderr, "rait_tapefd_ioctl:returning %d: %s\n",
-1,
strerror(errno)));
return -1;
}
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 (0 != func0) {
res = (*func0)(pr->fds[i]);
} else {
res = (*func1)(pr->fds[i], count);
}
rait_debug((stderr, "in kid, func ( %d ) returned %d errno %d\n", pr->fds[i], res, errno));
if (kid == 0)
exit(res);
} else {
rait_debug((stderr, "in parent, fork returned %d\n", kid));
pr->readres[i] = kid;
}
}
else {
if(0 != func0) {
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( pr->readres[i], &stat, 0);
if( WEXITSTATUS(stat) != 0 ) {
res = WEXITSTATUS(stat);
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, int count) {
return rait_tapefd_ioctl(0, tapefd_fsf, fd, count);
}
int rait_tapefd_rewind(int fd) {
return rait_tapefd_ioctl(tapefd_rewind, 0, fd, -1);
}
int rait_tapefd_unload(int fd) {
return rait_tapefd_ioctl(tapefd_unload, 0, fd, -1);
}
int rait_tapefd_weof(int fd, int count) {
return rait_tapefd_ioctl(0, tapefd_weof, fd, count);
}
int rait_tape_open(char *name, int flags, int 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 || 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) {
rait_lseek(fd, 0L, SEEK_SET);
}
int
rait_tapefd_can_fork(fd)
int fd;
{
return 0;
}
amanda-2.4.5/tape-src/output-null.c 0000644 0002005 0000313 00000007403 07631740464 012621 /*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: output-null.c,v 1.1.2.3.2.3 2003/03/06 21:44:20 martinea Exp $
*
* tapeio.c virtual tape interface for a null device.
*/
#include "amanda.h"
#include "tapeio.h"
#include "output-null.h"
#include "fileheader.h"
#ifndef R_OK
#define R_OK 4
#define W_OK 2
#endif
static long *amount_written = NULL;
static int open_count = 0;
int
null_tape_open(filename, flags, mask)
char *filename;
int flags;
int mask;
{
int fd;
if ((flags & 3) != O_RDONLY) {
flags &= ~3;
flags |= O_RDWR;
}
if ((fd = open("/dev/null", flags, mask)) >= 0) {
tapefd_setinfo_fake_label(fd, 1);
amtable_alloc((void **)&amount_written,
&open_count,
sizeof(*amount_written),
fd + 1,
10,
NULL);
amount_written[fd] = 0;
}
return fd;
}
ssize_t
null_tapefd_read(fd, buffer, count)
int fd;
void *buffer;
size_t count;
{
return read(fd, buffer, count);
}
ssize_t
null_tapefd_write(fd, buffer, count)
int fd;
const void *buffer;
size_t count;
{
int write_count = count;
long length;
long kbytes_left;
int r;
if (write_count <= 0) {
return 0; /* special case */
}
if ((length = tapefd_getinfo_length(fd)) > 0) {
kbytes_left = length - amount_written[fd];
if (write_count / 1024 > kbytes_left) {
write_count = kbytes_left * 1024;
}
}
amount_written[fd] += (write_count + 1023) / 1024;
if (write_count <= 0) {
errno = ENOSPC;
r = -1;
} else {
r = write(fd, buffer, write_count);
}
return r;
}
int
null_tapefd_close(fd)
int fd;
{
return close(fd);
}
void
null_tapefd_resetofs(fd)
int fd;
{
}
int
null_tapefd_status(fd, stat)
int fd;
struct am_mt_status *stat;
{
memset((void *)stat, 0, sizeof(*stat));
stat->online_valid = 1;
stat->online = 1;
return 0;
}
int
null_tape_stat(filename, buf)
char *filename;
struct stat *buf;
{
return stat("/dev/null", buf);
}
int
null_tape_access(filename, mode)
char *filename;
int mode;
{
return access("/dev/null", mode);
}
int
null_tapefd_rewind(fd)
int fd;
{
amount_written[fd] = 0;
return 0;
}
int
null_tapefd_unload(fd)
int fd;
{
amount_written[fd] = 0;
return 0;
}
int
null_tapefd_fsf(fd, count)
int fd, count;
{
return 0;
}
int
null_tapefd_weof(fd, count)
int fd, count;
{
return 0;
}
int
null_tapefd_can_fork(fd)
int fd;
{
return 0;
}
amanda-2.4.5/tape-src/tapeio.h 0000644 0002005 0000313 00000012443 07632203511 011563 /*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: tapeio.h,v 1.9.2.2.4.3.2.3 2003/03/07 20:55:37 martinea Exp $
*
* interface for tapeio.c
*/
#ifndef TAPEIO_H
#define TAPEIO_H
#include "amanda.h"
/*
* Tape drive status structure. This abstracts the things we are
* interested in from the free-for-all of what the various drivers
* supply.
*/
struct am_mt_status {
char online_valid; /* is the online flag valid? */
char bot_valid; /* is the BOT flag valid? */
char eot_valid; /* is the EOT flag valid? */
char protected_valid; /* is the protected flag valid? */
char flags_valid; /* is the flags field valid? */
char fileno_valid; /* is the fileno field valid? */
char blkno_valid; /* is the blkno field valid? */
char device_status_valid; /* is the device status field valid? */
char error_status_valid; /* is the device status field valid? */
char online; /* true if device is online/ready */
char bot; /* true if tape is at the beginning */
char eot; /* true if tape is at end of medium */
char protected; /* true if tape is write protected */
long flags; /* device flags, whatever that is */
long fileno; /* tape file number */
long blkno; /* block within file */
int device_status_size; /* size of orig device status field */
unsigned long device_status; /* "device status", whatever that is */
int error_status_size; /* size of orig error status field */
unsigned long error_status; /* "error status", whatever that is */
};
#define FAKE_LABEL "[fake-label]"
int tape_open ();
int tapefd_rewind P((int tapefd));
int tapefd_unload P((int tapefd));
int tapefd_fsf P((int tapefd, int count));
int tapefd_weof P((int tapefd, int count));
int tapefd_status P((int tapefd, struct am_mt_status *));
void tapefd_resetofs P((int tapefd));
ssize_t tapefd_read P((int tapefd, void *buffer, size_t count));
ssize_t tapefd_write P((int tapefd, const void *buffer, size_t count));
char *tapefd_rdlabel P((int tapefd, char **datestamp, char **label));
char *tapefd_wrlabel P((int tapefd,
char *datestamp,
char *label,
unsigned int s));
char *tapefd_wrendmark P((int tapefd, char *datestamp, unsigned int s));
int tapefd_eof P((int tapefd)); /* just used in tapeio-test */
int tapefd_close P((int tapefd));
int tapefd_can_fork P((int tapefd));
char *tape_unload P((char *dev));
char *tape_rewind P((char *dev));
char *tape_fsf P((char *dev, int count));
char *tape_rdlabel P((char *dev, char **datestamp, char **label));
char *tape_wrlabel P((char *dev,
char *datestamp,
char *label,
unsigned int size));
char *tape_wrendmark P((char *dev,
char *datestamp,
unsigned int size));
char *tape_writable P((char *dev));
int tape_access P((char *dev, int mode));
int tape_stat P((char *filename, struct stat *buf));
char *tapefd_getinfo_label P((int fd));
void tapefd_setinfo_label P((int fd, char *v));
char *tapefd_getinfo_host P((int fd));
void tapefd_setinfo_host P((int fd, char *v));
char *tapefd_getinfo_disk P((int fd));
void tapefd_setinfo_disk P((int fd, char *v));
int tapefd_getinfo_level P((int fd));
void tapefd_setinfo_level P((int fd, int v));
char *tapefd_getinfo_datestamp P((int fd));
void tapefd_setinfo_datestamp P((int fd, char *v));
long tapefd_getinfo_length P((int fd));
void tapefd_setinfo_length P((int fd, long v));
char *tapefd_getinfo_tapetype P((int fd));
void tapefd_setinfo_tapetype P((int fd, char *v));
int tapefd_getinfo_fake_label P((int fd));
void tapefd_setinfo_fake_label P((int fd, int v));
int tapefd_getinfo_ioctl_fork P((int fd));
void tapefd_setinfo_ioctl_fork P((int fd, int v));
void tapefd_set_master_fd P((int tapefd, int master_fd));
#ifdef HAVE_LINUX_ZFTAPE_H
int is_zftape P((const char *filename));
#endif
int tapeio_init_devname P((char * dev,
char **dev_left,
char **dev_right,
char **dev_next));
char *tapeio_next_devname P((char * dev_left,
char * dev_right,
char **dev_next));
#endif /* ! TAPEIO_H */
amanda-2.4.5/tape-src/tapetype.c 0000644 0002005 0000313 00000036565 10144440673 012147 /*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: tapetype.c,v 1.3.2.3.4.3.2.9.2.2 2004/11/10 16:28:43 martinea Exp $
*
* tests a tape in a given tape unit and prints a tapetype entry for
* it. */
#include "amanda.h"
#include "tapeio.h"
#define NBLOCKS 32 /* number of random blocks */
extern int optind;
static char *sProgName;
static char *tapedev;
static int fd;
static int blockkb = 32;
static int blocksize;
static char *randombytes = (char *) NULL;
#if USE_RAND
/* If the C library does not define random(), try to use rand() by
defining USE_RAND, but then make sure you are not using hardware
compression, because the low-order bits of rand() may not be that
random... :-( */
#define random() rand()
#define srandom(seed) srand(seed)
#endif
static void allocrandombytes() {
int i, j, page_size;
char *p;
if (randombytes == (char *)NULL) {
#if defined(HAVE_GETPAGESIZE)
page_size = getpagesize();
#else
page_size = 1024;
#endif
j = (NBLOCKS * blocksize) + page_size; /* buffer space plus one page */
j = am_round(j, page_size); /* even number of pages */
p = alloc(j);
i = (p - (char *)0) & (page_size - 1); /* page boundary offset */
if(i != 0) {
randombytes = p + page_size - i; /* round up to page boundary */
} else {
randombytes = p; /* alloc already on boundary */
}
}
}
static void initnotrandombytes() {
int i, j;
char *p;
allocrandombytes();
j =NBLOCKS * blocksize;
p = randombytes;
for(i=0; i < j; ++i) {
*p++ = (char) (i % 256);
}
}
static void initrandombytes() {
int i, j;
char *p;
allocrandombytes();
j = NBLOCKS * blocksize;
p = randombytes;
for(i=0; i < j; ++i) {
*p++ = (char)random();
}
}
static char *getrandombytes() {
static int counter = 0;
return randombytes + ((counter++ % NBLOCKS) * blocksize);
}
static int short_write;
int writeblock(fd)
int fd;
{
size_t w;
if ((w = tapefd_write(fd, getrandombytes(), blocksize)) == blocksize) {
return 1;
}
if (w >= 0) {
short_write = 1;
} else {
short_write = 0;
}
return 0;
}
/* returns number of blocks actually written */
size_t writeblocks(int fd, size_t nblks)
{
size_t blks = 0;
while (blks < nblks) {
if (! writeblock(fd)) {
return 0;
}
blks++;
}
return blks;
}
void usage()
{
fputs("usage: ", stderr);
fputs(sProgName, stderr);
fputs(" [-h]", stderr);
fputs(" [-c]", stderr);
fputs(" [-o]", stderr);
fputs(" [-b blocksize]", stderr);
fputs(" [-e estsize]", stderr);
fputs(" [-f tapedev]", stderr);
fputs(" [-t typename]", stderr);
fputc('\n', stderr);
}
void help()
{
usage();
fputs("\
-h display this message\n\
-c run hardware compression detection test only\n\
-o overwrite amanda tape\n\
-b blocksize record block size (default: 32k)\n\
-e estsize estimated tape size (default: 1g == 1024m)\n\
-f tapedev tape device name (default: $TAPE)\n\
-t typename tapetype name (default: unknown-tapetype)\n\
\n\
Note: disable hardware compression when running this program.\n\
", stderr);
}
int do_tty;
void show_progress(blocks, files)
size_t *blocks, *files;
{
fprintf(stderr, "wrote %ld %dKb block%s in %ld file%s",
(long)*blocks, blockkb, (*blocks == 1) ? "" : "s",
(long)*files, (*files == 1) ? "" : "s");
}
void do_pass(size, blocks, files, seconds)
size_t size, *blocks, *files;
time_t *seconds;
{
size_t blks;
time_t start, end;
int save_errno;
if (tapefd_rewind(fd) == -1) {
fprintf(stderr, "%s: could not rewind %s: %s\n",
sProgName, tapedev, strerror(errno));
exit(1);
}
time(&start);
while(1) {
if ((blks = writeblocks(fd, size)) <= 0 || tapefd_weof(fd, 1) != 0)
break;
*blocks += blks;
(*files)++;
if(do_tty) {
putc('\r', stderr);
show_progress(blocks, files);
}
}
save_errno = errno;
time(&end);
if (*blocks == 0) {
fprintf(stderr, "%s: could not write any data in this pass: %s\n",
sProgName, short_write ? "short write" : strerror(save_errno));
exit(1);
}
if(end <= start) {
/*
* Just in case time warped backward or the device is really, really
* fast (e.g. /dev/null testing).
*/
*seconds = 1;
} else {
*seconds = end - start;
}
if(do_tty) {
putc('\r', stderr);
}
show_progress(blocks, files);
fprintf(stderr, " in %ld second%s (%s)\n",
(long)*seconds, ((long)*seconds == 1) ? "" : "s",
short_write ? "short write" : strerror(save_errno));
}
void do_pass0(size, seconds, dorewind)
size_t size;
time_t *seconds;
int dorewind;
{
size_t blks;
time_t start, end;
int save_errno;
if (dorewind && tapefd_rewind(fd) == -1) {
fprintf(stderr, "%s: could not rewind %s: %s\n",
sProgName, tapedev, strerror(errno));
exit(1);
}
time(&start);
blks = writeblocks(fd, size);
tapefd_weof(fd, 1);
save_errno = errno;
time(&end);
if (blks <= 0) {
fprintf(stderr, "%s: could not write any data in this pass: %s\n",
sProgName, short_write ? "short write" : strerror(save_errno));
exit(1);
}
if(end <= start) {
/*
* Just in case time warped backward or the device is really, really
* fast (e.g. /dev/null testing).
*/
*seconds = 1;
} else {
*seconds = end - start;
}
}
int main(argc, argv)
int argc;
char *argv[];
{
size_t pass1blocks = 0;
size_t pass2blocks = 0;
time_t pass1time;
time_t pass2time;
time_t timediff;
size_t pass1files = 0;
size_t pass2files = 0;
size_t estsize;
size_t pass0size;
size_t pass1size;
size_t pass2size;
size_t blockdiff;
size_t filediff;
long filemark;
long speed;
size_t size;
char *sizeunits;
int ch;
char *suffix;
char *typename;
time_t now;
int hwcompr = 0;
int comprtstonly = 0;
int overwrite_label = 0;
int is_labeled = 0;
char *result;
char *datestamp = NULL;
char *label = NULL;
if ((sProgName = strrchr(*argv, '/')) == NULL) {
sProgName = *argv;
} else {
sProgName++;
}
estsize = 1024 * 1024; /* assume 1 GByte for now */
tapedev = getenv("TAPE");
typename = "unknown-tapetype";
while ((ch = getopt(argc, argv, "b:e:f:t:hco")) != EOF) {
switch (ch) {
case 'b':
blockkb = strtol(optarg, &suffix, 0);
if (*suffix == '\0' || *suffix == 'k' || *suffix == 'K') {
} else if (*suffix == 'm' || *suffix == 'M') {
blockkb *= 1024;
} else if (*suffix == 'g' || *suffix == 'G') {
blockkb *= 1024 * 1024;
} else {
fprintf(stderr, "%s: unknown size suffix \'%c\'\n", sProgName, *suffix);
return 1;
}
break;
case 'e':
estsize = strtol(optarg, &suffix, 0);
if (*suffix == '\0' || *suffix == 'k' || *suffix == 'K') {
} else if (*suffix == 'm' || *suffix == 'M') {
estsize *= 1024;
} else if (*suffix == 'g' || *suffix == 'G') {
estsize *= 1024 * 1024;
} else {
fprintf(stderr, "%s: unknown size suffix \'%c\'\n", sProgName, *suffix);
return 1;
}
break;
case 'f':
tapedev = stralloc(optarg);
break;
case 't':
typename = stralloc(optarg);
break;
case 'c':
comprtstonly = 1;
break;
case 'h':
help();
return 1;
break;
case 'o':
overwrite_label=1;
break;
default:
fprintf(stderr, "%s: unknown option \'%c\'\n", sProgName, ch);
/* fall through to ... */
case '?':
usage();
return 1;
break;
}
}
blocksize = blockkb * 1024;
if (tapedev == NULL || optind < argc) {
usage();
return 1;
}
/* verifier tape */
fd = tape_open(tapedev, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "%s: could not open %s: %s\n",
sProgName, tapedev, strerror(errno));
return 1;
}
if((result = tapefd_rdlabel(fd, &datestamp, &label)) == NULL) {
is_labeled = 1;
}
else if (strcmp(result,"not an amanda tape") == 0) {
is_labeled = 2;
}
if(tapefd_rewind(fd) == -1) {
fprintf(stderr, "%s: could not rewind %s: %s\n",
sProgName, tapedev, strerror(errno));
tapefd_close(fd);
return 1;
}
tapefd_close(fd);
if(is_labeled == 1 && overwrite_label == 0) {
fprintf(stderr, "%s: The tape is an amanda tape, use -o to overwrite the tape\n",
sProgName);
return 1;
}
else if(is_labeled == 2 && overwrite_label == 0) {
fprintf(stderr, "%s: The tape is already used, use -o to overwrite the tape\n",
sProgName);
return 1;
}
fd = tape_open(tapedev, O_RDWR);
if (fd == -1) {
fprintf(stderr, "%s: could not open %s: %s\n",
sProgName, tapedev, strerror(errno));
return 1;
}
do_tty = isatty(fileno(stderr));
/*
* Estimate pass: write twice a small file, once with compressable
* data and once with uncompressable data.
* The theory is that if the drive is in hardware compression mode
* we notice a significant difference in writing speed between the two
* (at least if we can provide data as fast the tape streams).
*/
initnotrandombytes();
fprintf(stderr, "Estimate phase 1...");
pass0size = 8 * 1024 / blockkb;
pass1time = 0;
pass2time = 0;
/*
* To get accurate results, we should write enough data
* so that rewind/start/stop time is small compared to
* the total time; let's take 10%.
* The timer has a 1 sec granularity, so the test
* should take at least 10 seconds to measure a
* difference with 10% accuracy; let's take 25 seconds.
*/
while (pass1time < 25 || ((100*(pass2time-pass1time)/pass2time) >= 10) ) {
if (pass1time != 0) {
int i = pass1time;
do {
pass0size *= 2;
i *= 2;
} while (i < 25);
}
/*
* first a dummy pass to rewind, stop, start and
* get drive streaming, then do the real timing
*/
do_pass0(pass0size, &pass2time, 1);
do_pass0(pass0size, &pass1time, 0);
if (pass0size >= 10 * 1024 * 1024) {
fprintf(stderr,
"\rTape device is