/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
+#include <roken.h>
-#include <sys/types.h>
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#else
-#include <sys/time.h>
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#endif
-#include <stdlib.h>
#include <rx/xdr.h>
#include <rx/rx.h>
#include <lwp.h>
#include <lock.h>
-#include <errno.h>
#include <afs/tcdata.h>
#include <afs/bubasics.h>
#include <afs/budb_client.h>
+#include <afs/butm_prototypes.h>
#include <afs/vldbint.h>
#include <afs/ktime.h>
#include <afs/vlserver.h>
+#include <afs/afsint.h>
#include <afs/volser.h>
+#include <afs/volser_prototypes.h>
#include <afs/volint.h>
#include <afs/cellconfig.h>
+#include <afs/bucoord_prototypes.h>
+#include "butc_internal.h"
#include "error_macros.h"
#include "butc_xbsa.h"
#include "afs/butx.h"
-
/* GLOBAL CONFIGURATION PARAMETERS */
extern int dump_namecheck;
extern int queryoperator;
dlqlinkT savedEntries;
dlqlinkT entries_to_flush;
-afs_int32 flushSavedEntries(), finishDump(), finishTape(), useTape(),
-addVolume();
-
-extern struct rx_connection *UV_Bind();
-
extern afs_int32 groupId;
extern afs_int32 BufferSize;
extern afs_int32 statusSize;
* 6) Ensure bucoord status calls work
*
* notes
- * pass 3:
+ * pass 3:
* keep token timeout. If no user reponse (idle time > some period)
* and tokens about to time out, terminate dump. This provides at
* least something usable.
*/
-#define DUMPNAME(dumpname, name, dbDumpId) \
- if (dbDumpId == 0) \
- sprintf(dumpname, "%s", name); \
- else \
- sprintf(dumpname, "%s (DumpId %u)", name, dbDumpId);
-
-#if defined(AFS_NT40_ENV) || (defined(AFS_DARWIN_ENV) && !defined(AFS_DARWIN60_ENV)) || defined(AFS_SUN4_ENV)
-int
-localtime_r(time_t * t, struct tm *tm)
-{
- memcpy(tm, localtime(t), sizeof(struct tm));
-}
-#endif
-
struct dumpRock {
/* status only */
int tapeSeq;
struct dumpNode *node;
};
+/* Forward declarations */
+
+int makeVolumeHeader(struct volumeHeader *, struct dumpRock *, int);
+int volumeHeader_hton(struct volumeHeader *, struct volumeHeader *);
+char retryPrompt(char *, afs_int32, afs_uint32);
+int getDumpTape(struct dumpRock *, int, afs_int32);
+int getXBSATape(struct dumpRock *);
+afs_int32 createDump(struct dumpRock *);
+
/* configuration variables */
#define HITEOT(code) ((code == BUTM_IO) || (code == BUTM_EOT) || (code == BUTM_IOCTL))
extern int autoQuery;
calcExpirationDate(afs_int32 expType, afs_int32 expDate, afs_int32 createTime)
{
struct ktime_date kd;
- afs_int32 Add_RelDate_to_Time();
switch (expType) {
case BC_REL_EXPDATE:
*/
Int32To_ktimeRelDate(expDate, &kd);
return (Add_RelDate_to_Time(&kd, createTime));
- break;
case BC_ABS_EXPDATE:
return (expDate);
- break;
case BC_NO_EXPDATE:
default:
}
}
-afs_int32 curr_bserver = 0;
+afs_uint32 curr_bserver = 0;
struct rx_connection *curr_fromconn = (struct rx_connection *)0;
struct rx_connection *
-Bind(afs_int32 server)
+Bind(afs_uint32 server)
{
if (curr_fromconn) {
if (curr_bserver == server) /* Keep connection if have it */
/* notes
* 1) save the chunksize or otherwise ensure tape space remaining is
* check frequently enough
- * 2) This is called once. For partial dumps, need to
+ * 2) This is called once. For partial dumps, need to
* ensure that the tape device is left in the correct state for
* further dumps.
- *
+ *
*/
#define BIGCHUNK 102400
buffer = bufferBlock + BUTM_HDRSIZE;
/* Dump one volume fragment at a time until we dump the full volume.
- * A volume with more than 1 fragment means the volume will 'span'
+ * A volume with more than 1 fragment means the volume will 'span'
* 2 or more tapes.
*/
for (fragmentNumber = 1; !endofvolume; fragmentNumber++) { /*frag */
/* Create and Write the volume header */
makeVolumeHeader(&hostVolumeHeader, dparamsPtr, fragmentNumber);
hostVolumeHeader.contd = ((fragmentNumber == 1) ? 0 : TC_VOLCONTD);
- volumeHeader_hton(&hostVolumeHeader, buffer);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)buffer);
rc = butm_WriteFileData(tapeInfoPtr, buffer, 1,
sizeof(hostVolumeHeader));
chunkSize = 0;
fragmentvolume = 0;
while (!endofvolume && !fragmentvolume) { /*w */
- bytesread = 0;
-
/* Check for abort in the middle of writing data */
if (volBytesRead >= chunkSize) {
chunkSize += BIGCHUNK;
/* Determine how much data to read in upcoming RX_Read() call */
toread = dataSize;
/* Check if we are close to the EOT. There should at least be some
- * data on the tape before it is switched. HACK: we have to split a
- * volume across tapes because the volume trailer says the dump
- * continues on the next tape (and not the filemark). This could
- * result in a volume starting on one tape (no volume data dumped) and
- * continued on the next tape. It'll work, just requires restore to
+ * data on the tape before it is switched. HACK: we have to split a
+ * volume across tapes because the volume trailer says the dump
+ * continues on the next tape (and not the filemark). This could
+ * result in a volume starting on one tape (no volume data dumped) and
+ * continued on the next tape. It'll work, just requires restore to
* switch tapes. This allows many small volumes (<16K) to be dumped.
*/
kRemaining = butm_remainingKSpace(tapeInfoPtr);
}
}
+#ifdef xbsa
+ /* Set aside space for the trailing volume header when using large buffers. */
+ if (XBSAMAXBUFFER < toread + sizeof(hostVolumeHeader)) {
+ toread = XBSAMAXBUFFER - sizeof(hostVolumeHeader);
+ }
+#endif
+
/* Read some volume data. */
if (fragmentvolume) {
bytesread = 0;
hostVolumeHeader.contd = (endofvolume ? 0 : TC_VOLCONTD);
hostVolumeHeader.magic = TC_VOLENDMAGIC;
hostVolumeHeader.endTime = (endofvolume ? time(0) : 0);
- volumeHeader_hton(&hostVolumeHeader, &buffer[bytesread]);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)&buffer[bytesread]);
bytesread += sizeof(hostVolumeHeader);
}
dparamsPtr->curVolumeStatus = DUMP_SUCCESS;
error_exit:
- /*
+ /*
* If we hit the end, see if this is the first volume on the tape or not.
* Also, mark the tape as finished if the tape contains other dumps.
*/
}
}
- /*
+ /*
* This is used when an error occurs part way into a volume dump. Clean
* the tape state by writing an FileEnd mark. Forgo this action if we hit
* the end of tape.
afs_uint32 statuscount = statusSize, tsize = 0, esize;
afs_hyper_t estSize;
- char dumpIdStr[XBSA_MAX_OSNAME];
char volumeNameStr[XBSA_MAX_PATHNAME];
static char *dumpDescription = "AFS volume dump";
static char *objectDescription = "XBSA - butc";
dparamsPtr->curVolStartPos = tapeInfoPtr->position;
/* Tell XBSA what the name and size of volume to write */
- strcpy(dumpIdStr, butcdumpIdStr); /* "backup_afs_volume_dumps" */
- sprintf(volumeNameStr, "/%d", dparamsPtr->databaseDumpId);
- strcat(volumeNameStr, "/");
- strcat(volumeNameStr, curDump->name); /* <dumpid>/<volname> */
+ snprintf(volumeNameStr, sizeof(volumeNameStr), "/%d/%s",
+ dparamsPtr->databaseDumpId, curDump->name);
hset32(estSize, esize);
hshlft(estSize, 10); /* Multiply by 1024 so its in KB */
- rc = xbsa_WriteObjectBegin(&butxInfo, dumpIdStr, volumeNameStr,
+ rc = xbsa_WriteObjectBegin(&butxInfo, butcdumpIdStr, volumeNameStr,
xbsalGName, estSize, dumpDescription,
objectDescription);
if (rc != XBSA_SUCCESS) {
/* Create and Write the volume header */
makeVolumeHeader(&hostVolumeHeader, dparamsPtr, 1);
hostVolumeHeader.contd = 0;
- volumeHeader_hton(&hostVolumeHeader, buffer);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)buffer);
- rc = xbsa_WriteObjectData(&butxInfo, buffer, sizeof(struct volumeHeader),
- &bytesWritten);
+ rc = xbsa_WriteObjectData(&butxInfo, buffer,
+ sizeof(struct volumeHeader), &bytesWritten);
if (rc != XBSA_SUCCESS) {
ErrorLog(1, taskId, rc, 0,
"Unable to write VolumeHeader data to the server\n");
bytesWritten = sizeof(struct volumeHeader);
if (bytesWritten != sizeof(struct volumeHeader)) {
ErrorLog(1, taskId, rc, 0,
- "The size of VolumeHeader written (%d) does not equal its actual size (%d)\n",
+ "The size of VolumeHeader written (%d) does not equal its actual size (%" AFS_SIZET_FMT ")\n",
bytesWritten, sizeof(struct volumeHeader));
ERROR_EXIT(TC_INTERNALERROR);
}
volBytesRead = 0;
chunkSize = 0;
while (!endofvolume) { /*w */
- bytesread = 0;
-
/* Check for abort in the middle of writing data */
if (volBytesRead >= chunkSize) {
chunkSize += BIGCHUNK;
hostVolumeHeader.contd = 0;
hostVolumeHeader.magic = TC_VOLENDMAGIC;
hostVolumeHeader.endTime = time(0);
- volumeHeader_hton(&hostVolumeHeader, &buffer[bytesread]);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)&buffer[bytesread]);
bytesread += sizeof(hostVolumeHeader);
/* End the dump and transaction with the volserver. We end it now, before
- * we make the XBSA call because if XBSA blocks, we could time out on the
+ * we make the XBSA call because if XBSA blocks, we could time out on the
* volserver (After last read, the transaction with the volserver is idle).
*/
rc = rx_EndCall(fromcall, 0);
abort_exit:
dparamsPtr->curVolumeStatus = DUMP_FAILED;
ERROR_EXIT(code);
+#else
+ return 0;
#endif
}
-#ifdef AFS_DEC_ENV
-#define HOSTADDR(sockaddr) (sockaddr)->sin_addr.S_un.S_addr
-#else
#define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
-#endif
/* dumpPass
* Go through the list of volumes to dump, dumping each one. The action
int action, e;
afs_int32 code = 0, tcode, dvcode;
char ch;
- char retryPrompt();
struct vldbentry vldbEntry;
struct sockaddr_in server;
afs_int32 tapepos;
switch (curDump->vtype) {
case BACKVOL:
- if (!(vldbEntry.flags & BACK_EXISTS)) {
+ if (!(vldbEntry.flags & VLF_BACKEXISTS)) {
ErrorLog(0, taskId, 0, 0,
"Volume %s (%u) failed - Backup volume no longer exists\n",
curDump->name, curDump->vid);
case RWVOL:
for (e = 0; e < vldbEntry.nServers; e++) { /* Find the RW volume */
- if (vldbEntry.serverFlags[e] & ITSRWVOL)
+ if (vldbEntry.serverFlags[e] & VLSF_RWVOL)
break;
}
break;
if (e >= vldbEntry.nServers) { /* Didn't find RO volume */
for (e = 0; e < vldbEntry.nServers; e++) { /* Find the first RO volume */
- if (vldbEntry.serverFlags[e] & ITSROVOL)
+ if (vldbEntry.serverFlags[e] & VLSF_ROVOL)
break;
}
}
curDump->name, curDump->vid);
curDump->hostAddr = 0;
continue;
- break;
}
if (e >= vldbEntry.nServers) {
if (checkAbortByTaskId(taskId))
ERROR_EXIT(TC_ABORTEDBYREQUEST);
- /* Establish connection to volume - UV_ routine expects
- * host address in network order
+ /* Establish connection to volume - UV_ routine expects
+ * host address in network order
*/
if (CONF_XBSA) {
dvcode = xbsaDumpVolume(curDump, dparamsPtr);
case 'r': /* retry */
dparamsPtr->curVolume--; /* redump this volume */
continue;
- break;
case 'o': /* omit */
ErrorLog(1, taskId, 0, 0, "Volume %s (%u) omitted\n",
curDump->name, curDump->vid);
dparamsPtr->curVolume--; /* redump this volume */
continue;
- break;
case DUMP_NORETRYEOT:
ErrorLog(1, taskId, 0, 0,
return (code);
}
-int
-Dumper(struct dumpNode *nodePtr)
+void *
+Dumper(void *param)
{
+ struct dumpNode *nodePtr = (struct dumpNode *)param;
struct dumpRock dparams;
struct butm_tapeInfo tapeInfo;
int pass;
int dumpedvolumes = 0;
int nodumpvolumes = 0;
char strlevel[5];
- char msg[20];
- char finishedMsg1[50];
- char finishedMsg2[50];
+ char msg[128];
+ char finishedMsg1[128];
+ char finishedMsg2[128];
time_t startTime = 0;
time_t endTime = 0;
afs_int32 allocbufferSize;
extern struct deviceSyncNode *deviceLatch;
extern struct tapeConfig globalTapeConfig;
- extern afs_int32 createDump();
+ afs_pthread_setname_self("dumper");
taskId = nodePtr->taskID; /* Get task Id */
setStatus(taskId, DRIVE_WAIT);
EnterDeviceQueue(deviceLatch);
* Used when requesting a tape. Done now because once we create the dump, the
* routine will then find the newly created dump.
*/
- sprintf(strlevel, "%d", nodePtr->level);
+ snprintf(strlevel, sizeof(strlevel), "%d", nodePtr->level);
code =
bcdb_FindLatestDump(nodePtr->volumeSetName, strlevel,
&dparams.lastDump);
break;
}
- /*
+ /*
* Log the error but ignore it since the dump is effectively done.
* Scantape may assume another volume and ask for next tape.
*/
if (!CONF_XBSA) {
code = butm_WriteEOT(&tapeInfo);
if (code)
- TapeLog(taskId, code, tapeInfo.error,
+ TapeLog(0, taskId, code, tapeInfo.error,
"Warning: Can't write end-of-dump on tape\n");
}
lastPass = 1; /* In case we aborted */
- DUMPNAME(finishedMsg1, nodePtr->dumpSetName, dparams.databaseDumpId);
- sprintf(finishedMsg2, "%d volumes dumped", dumpedvolumes);
+ /* Format and log finished message. */
+ snprintf(finishedMsg1, sizeof(finishedMsg1), "%s", nodePtr->dumpSetName);
+ if (dparams.databaseDumpId != 0) {
+ snprintf(msg, sizeof(msg), " (DumpId %u)", dparams.databaseDumpId);
+ strlcat(finishedMsg1, msg, sizeof(finishedMsg1));
+ }
+ snprintf(finishedMsg2, sizeof(finishedMsg2),
+ "%d volumes dumped", dumpedvolumes);
if (failedvolumes) {
- sprintf(msg, ", %d failed", failedvolumes);
- strcat(finishedMsg2, msg);
+ snprintf(msg, sizeof(msg), ", %d failed", failedvolumes);
+ strlcat(finishedMsg2, msg, sizeof(finishedMsg2));
}
if (nodumpvolumes) {
- sprintf(msg, ", %d unchanged", nodumpvolumes);
- strcat(finishedMsg2, msg);
+ snprintf(msg, sizeof(msg), ", %d unchanged", nodumpvolumes);
+ strlcat(finishedMsg2, msg, sizeof(finishedMsg2));
}
if (code == TC_ABORTEDBYREQUEST) {
if (centralLogIO && startTime) {
long timediff;
afs_int32 hrs, min, sec, tmp;
- char line[1024];
+ char *line = NULL;
struct tm tmstart, tmend;
localtime_r(&startTime, &tmstart);
min = tmp / 60;
sec = tmp % 60;
- sprintf(line,
+ code = asprintf(&line,
"%-5d %02d/%02d/%04d %02d:%02d:%02d "
"%02d/%02d/%04d %02d:%02d:%02d " "%02d:%02d:%02d "
- "%s %d of %d volumes dumped (%ld KB)\n", taskId,
+ "%s %d of %d volumes dumped (%lu KB)\n", taskId,
tmstart.tm_mon + 1, tmstart.tm_mday, tmstart.tm_year + 1900,
tmstart.tm_hour, tmstart.tm_min, tmstart.tm_sec,
tmend.tm_mon + 1, tmend.tm_mday, tmend.tm_year + 1900,
tmend.tm_hour, tmend.tm_min, tmend.tm_sec, hrs, min, sec,
nodePtr->volumeSetName, dumpedvolumes,
dumpedvolumes + failedvolumes,
- dparams.tapeInfoPtr->kBytes + 1);
-
- fwrite(line, strlen(line), 1, centralLogIO);
- fflush(centralLogIO);
+ afs_printable_uint32_lu(dparams.tapeInfoPtr->kBytes + 1));
+ if (code < 0)
+ line = NULL;
+ if (line != NULL) {
+ fwrite(line, strlen(line), 1, centralLogIO);
+ fflush(centralLogIO);
+ }
+ free(line);
}
setStatus(taskId, TASK_DONE);
FreeNode(taskId); /* free the dump node */
LeaveDeviceQueue(deviceLatch);
- return (code);
+ return (void *)(intptr_t)(code);
}
#define BELLTIME 60 /* 60 seconds before a bell rings */
* volume parameters describe the volume that failed
* entry:
* volumeName - name of volume
- * volumeId - volume id
+ * volumeId - volume id
* taskId - for job contrl
* fn return:
* character typed by user, one of r, o or a
printf("a - abort, the entire dump\n");
while (1) {
- FFlushInput(stdin);
+ FFlushInput();
putchar(BELLCHAR);
fflush(stdout);
start = time(0);
while (1) {
-#ifdef AFS_PTHREAD_ENV
- code = GetResponseKey(5, &ch); /* ch stores key pressed */
-#else
code = LWP_GetResponseKey(5, &ch); /* ch stores key pressed */
-#endif
if (code == 1)
break; /* input is available */
printf(" pName = %s\n", tl->pName);
printf(" size = %u\n", tl->size);
printf(" dumpPath = %s\n", tl->dumpPath);
+ return 0;
}
/* getXBSATape
afs_int32 tapepos, lastpos;
extern struct tapeConfig globalTapeConfig;
- extern struct udbHandleS udbHandle;
askForTape = interactiveFlag;
dparamsPtr->wroteLabel = 0;
code = bcdb_FindDumpByID(dmp, &de);
if (code)
break;
- sprintf(strlevel, "%d", de.level);
+ snprintf(strlevel, sizeof(strlevel), "%d", de.level);
code =
bcdb_FindLatestDump(de.volumeSetName, strlevel,
&de2);
/*
* Now have the right tape. Create a new label for the tape
- * Appended labels have the dump's dumpId - labels at beginnings of
+ * Appended labels have the dump's dumpId - labels at beginnings of
* tape have the initial dump's dumpId.
* Appended labels do not increment the useCount.
* Labels at beginnings of tape use the most future expiration of the dump set.
strcpy(vhptr->dumpSetName, nodePtr->dumpSetName);
strcpy(vhptr->preamble, "H++NAME#");
strcpy(vhptr->postamble, "T--NAME#");
-
+
return (code);
}
{
struct volumeHeader volHdr;
+ memset(&volHdr, 0, sizeof(volHdr));
+
strcpy(volHdr.preamble, hostPtr->preamble);
strcpy(volHdr.postamble, hostPtr->postamble);
strcpy(volHdr.volumeName, hostPtr->volumeName);
volHdr.cloneDate = htonl(hostPtr->cloneDate);
memcpy(netPtr, &volHdr, sizeof(struct volumeHeader));
+ return 0;
}
/* database related routines */
/* DeleteDump
*
*/
-int
-DeleteDump(struct deleteDumpIf *ptr)
+void *
+DeleteDump(void *param)
{
+ struct deleteDumpIf *ptr = (struct deleteDumpIf *)param;
+
afs_int32 taskId;
afs_int32 rc, code = 0;
afs_uint32 dumpid;
extern struct udbHandleS udbHandle;
extern struct deviceSyncNode *deviceLatch;
+ dumpid = ptr->dumpID;
+ taskId = ptr->taskId; /* Get task Id */
+
+ afs_pthread_setname_self("deletedump");
setStatus(taskId, DRIVE_WAIT);
EnterDeviceQueue(deviceLatch);
clearStatus(taskId, DRIVE_WAIT);
- dumpid = ptr->dumpID;
- taskId = ptr->taskId; /* Get task Id */
-
printf("\n\n");
TapeLog(2, taskId, 0, 0, "Delete Dump %u\n", dumpid);
for (i = 0; i < vl.budb_volumeList_len; i++) {
if (dumpEntry.flags & BUDB_DUMP_BUTA) {
/* dump was from buta, use old buta style names */
- sprintf(dumpIdStr, "/%d", dumpid);
- strcpy(volumeNameStr, "/");
- strcat(volumeNameStr, (char *)vl.budb_volumeList_val[i].name);
+ snprintf(dumpIdStr, sizeof(dumpIdStr), "/%d", dumpid);
+ snprintf(volumeNameStr, sizeof(volumeNameStr), "/%s",
+ (char *)vl.budb_volumeList_val[i].name);
} else { /* BUDB_DUMP_ADSM */
/* dump was from butc to ADSM, use butc names */
- strcpy(dumpIdStr, butcdumpIdStr);
- sprintf(volumeNameStr, "/%d", dumpid);
- strcat(volumeNameStr, "/");
- strcat(volumeNameStr, (char *)vl.budb_volumeList_val[i].name);
+ snprintf(dumpIdStr, sizeof(dumpIdStr), "%s", butcdumpIdStr);
+ snprintf(volumeNameStr, sizeof(volumeNameStr), "/%d/%s",
+ dumpid, (char *)vl.budb_volumeList_val[i].name);
}
rc = xbsa_DeleteObject(&butxInfo, dumpIdStr, volumeNameStr);
code = BUTX_DELETENOVOL;
setStatus(taskId, TASK_ERROR);
}
- return (code);
+ return (void *)(uintptr_t)(code);
}
#endif