/*
* 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 <afs/stds.h>
#if defined(AFS_LINUX24_ENV)
#define _REGEX_RE_COMP
#endif
#include <sys/types.h>
-#if defined(AFS_LINUX24_ENV)
-#include <regex.h>
-#endif
#include <afs/cmd.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#endif
#include <errno.h>
#include <afs/com_err.h>
+#include <afs/afsutil.h>
#include <afs/budb.h>
+#include <afs/budb_prototypes.h>
#include <afs/butc.h>
#include <afs/bubasics.h> /* PA */
#include <afs/volser.h>
#include <afs/tcdata.h>
#include <afs/butx.h>
#include <afs/vsutils_prototypes.h>
+#ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
+#include <regex.h>
+#endif
#include "bc.h"
#include "error_macros.h"
+#include "bucoord_internal.h"
#include "bucoord_prototypes.h"
-#include "regex.h"
extern struct bc_config *bc_globalConfig;
extern struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
extern struct ubik_client *cstruct;
extern char *whoami;
-extern struct ktc_token ttoken;
char *loadFile;
extern afs_int32 lastTaskCode;
static int DBLookupByVolume(char *volumeName);
int
-bc_EvalVolumeSet(struct bc_config *aconfig,
- struct bc_volumeSet *avs,
- struct bc_volumeDump **avols,
+bc_EvalVolumeSet(struct bc_config *aconfig,
+ struct bc_volumeSet *avs,
+ struct bc_volumeDump **avols,
struct ubik_client *uclient)
{ /*bc_EvalVolumeSet */
int code = -1;
};
afs_int32
-getSPEntries(afs_uint32 server, afs_int32 partition,
- struct serversort **serverlist,
- struct serversort **ss,
+getSPEntries(afs_uint32 server, afs_int32 partition,
+ struct serversort **serverlist,
+ struct serversort **ss,
struct partitionsort **ps)
{
if (!(*ss) || ((*ss)->ipaddr != server)) {
if (!(*ss)) {
*ss = (struct serversort *)malloc(sizeof(struct serversort));
if (!(*ss)) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
*ss = 0;
return (BC_NOMEM);
}
if (!(*ps)) {
*ps = (struct partitionsort *)malloc(sizeof(struct partitionsort));
if (!(*ps)) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
free(*ss);
*ps = 0;
*ss = 0;
}
afs_int32
-randSPEntries(struct serversort *serverlist,
+randSPEntries(struct serversort *serverlist,
struct bc_volumeDump **avols)
{
struct serversort *ss, **pss;
}
static int
-EvalVolumeSet2(struct bc_config *aconfig,
- struct bc_volumeSet *avs,
- struct bc_volumeDump **avols,
+EvalVolumeSet2(struct bc_config *aconfig,
+ struct bc_volumeSet *avs,
+ struct bc_volumeDump **avols,
struct ubik_client *uclient)
{ /*EvalVolumeSet2 */
struct bc_volumeEntry *tve;
/* For each of the volume set entries - collect the volumes that match it */
for (tve = avs->ventries; tve; tve = tve->next) {
- /* Put together a call to the vlserver for this vlentry. The
+ /* Put together a call to the vlserver for this vlentry. The
* performance gain is from letting the vlserver expand the
* volumeset and not this routine.
*/
entries[e].serverPartition[ei], &servers,
&ss, &ps);
if (tcode) {
- afs_com_err(whoami, tcode, "");
+ afs_com_err(whoami, tcode, NULL);
ERROR(tcode);
}
tvd = (struct bc_volumeDump *)
malloc(sizeof(struct bc_volumeDump));
if (!tvd) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
ERROR(BC_NOMEM);
}
memset(tvd, 0, sizeof(*tvd));
tvd->name = (char *)malloc(strlen(entries[e].name) + 10);
if (!(tvd->name)) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
free(tvd);
ERROR(BC_NOMEM);
}
* EvalVolumeSetOld
*
* Description:
- * Takes the entries in a volumeset and expands them into a list of
+ * Takes the entries in a volumeset and expands them into a list of
* volumes. Every VLDB volume entry is looked at and compared to the
* volumeset entries.
*
- * When matching a VLDB volume entry to a volumeset entry,
+ * When matching a VLDB volume entry to a volumeset entry,
* 1. If the RW volume entry matches, that RW volume is used.
* 2. Otherwise, if the BK volume entry matches, the BK volume is used.
* 3. Finally, if the RO volume entry matches, the RO volume is used.
- * For instance: A volumeset entry of ".* .* user.t.*" will match volume
- * "user.troy" and "user.troy.backup". The rules will use
+ * For instance: A volumeset entry of ".* .* user.t.*" will match volume
+ * "user.troy" and "user.troy.backup". The rules will use
* the RW volume "user.troy".
*
* When a VLDB volume entry matches a volumeset entry (be it RW, BK or RO),
- * that volume is used and matches against any remaining volumeset entries
+ * that volume is used and matches against any remaining volumeset entries
* are not even done.
* For instance: A 1st volumeset entry ".* .* .*.backup" will match with
- * "user.troy.backup". Its 2nd volumeset entry ".* .* .*"
- * would have matched its RW volume "user.troy", but the first
+ * "user.troy.backup". Its 2nd volumeset entry ".* .* .*"
+ * would have matched its RW volume "user.troy", but the first
* match is used and the second match isn't even done.
*
* Arguments:
* aconfig : Global configuration info.
- * avs :
+ * avs :
* avols : Ptr to linked list of entries describing volumes to dump.
* uclient : Ptr to Ubik client structure.
*
*-----------------------------------------------------------------------------
*/
static int
-EvalVolumeSet1(struct bc_config *aconfig,
+EvalVolumeSet1(struct bc_config *aconfig,
struct bc_volumeSet *avs,
- struct bc_volumeDump **avols,
+ struct bc_volumeDump **avols,
struct ubik_client *uclient)
{ /*EvalVolumeSet1 */
afs_int32 code; /*Result of various calls */
- char *errm;
struct bc_volumeDump *tvd; /*Ptr to new dump instance */
struct bc_volumeEntry *tve, *ctve; /*Ptr to new volume entry instance */
char patt[256]; /*Composite regex; also, target string */
int foundentry = 0;
struct serversort *servers = 0, *ss = 0;
struct partitionsort *ps = 0;
+#ifdef HAVE_POSIX_REGEX
+ regex_t re;
+ int need_regfree = 0;
+#else
+ char *errm;
+#endif
*avols = (struct bc_volumeDump *)0;
ctve = (struct bc_volumeEntry *)0; /* no compiled entry */
/* If the volume entry is not compiled, then compile it */
if (ctve != tve) {
sprintf(patt, "^%s$", tve->name);
+#ifdef HAVE_POSIX_REGEX
+ if (regcomp(&re, patt, REG_NOSUB) != 0) {
+ afs_com_err(whoami, 0, "Can't compile regular expression '%s'", patt);
+ return (-1);
+ }
+ need_regfree = 1;
+#else
errm = (char *)re_comp(patt);
if (errm) {
afs_com_err(whoami, 0,
patt, errm);
return (-1);
}
+#endif
ctve = tve;
}
if (entry.serverFlags[srvpartpair] & ITSRWVOL) {
if (entry.flags & RW_EXISTS) {
sprintf(patt, "%s", entry.name);
+#ifdef HAVE_POSIX_REGEX
+ code = regexec(&re, patt, 0, NULL, 0);
+ if (code == 0) {
+#else
code = re_exec(patt);
if (code == 1) {
+#endif
found = 1;
foundentry = srvpartpair;
volType = RWVOL;
}
}
- /* If the BK name matches the volume set entry, take
+ /* If the BK name matches the volume set entry, take
* it and exit. Second choice is to use the BK volume.
*/
if (entry.flags & BACK_EXISTS) {
sprintf(patt, "%s.backup", entry.name);
+#ifdef HAVE_POSIX_REGEX
+ code = regexec(&re, patt, 0, NULL, 0);
+ if (code == 0) {
+#else
code = re_exec(patt);
if (code == 1) {
+#endif
found = 1;
foundentry = srvpartpair;
volType = BACKVOL;
else if (!found && (entry.serverFlags[srvpartpair] & ITSROVOL)
&& (entry.flags & RO_EXISTS)) {
sprintf(patt, "%s.readonly", entry.name);
+#ifdef HAVE_POSIX_REGEX
+ code = regexec(&re, patt, 0, NULL, 0);
+ if (code == 0) {
+#else
code = re_exec(patt);
if (code == 1) {
+#endif
found = 1;
foundentry = srvpartpair;
volType = ROVOL;
entry.serverPartition[foundentry], &servers,
&ss, &ps);
if (code) {
- afs_com_err(whoami, code, "");
+ afs_com_err(whoami, code, NULL);
return (code);
}
tvd = (struct bc_volumeDump *)
malloc(sizeof(struct bc_volumeDump));
if (!tvd) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return (BC_NOMEM);
}
memset(tvd, 0, sizeof(*tvd));
tvd->name = (char *)malloc(strlen(entry.name) + 10);
if (!(tvd->name)) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
free(tvd);
return (BC_NOMEM);
}
} /*f */
} /*ve */
} /*w */
+#ifdef HAVE_POSIX_REGEX
+ if (need_regfree)
+ regfree(&re);
+#endif
/* Randomly link the volumedump entries together */
randSPEntries(servers, avols);
return (0);
} /*EvalVolumeSet1 */
-/* compactDateString
- * print out a date in compact format, 16 chars, format is
- * mm/dd/yyyy hh:mm
- * entry:
- * date_long - ptr to a long containing the time
- * exit:
- * ptr to a string containing a representation of the date
- */
char *
-compactDateString(afs_uint32 *date_long, char *string, afs_int32 size)
+compactTimeString(time_t *date, char *string, afs_int32 size)
{
struct tm *ltime;
if (!string)
- return 0;
+ return NULL;
- if (*date_long == NEVERDATE) {
+ if (*date == NEVERDATE) {
sprintf(string, "NEVER");
} else {
- time_t t = *date_long;
- ltime = localtime(&t);
- /* prints date in U.S. format of mm/dd/yyyy */
+ ltime = localtime(date);
strftime(string, size, "%m/%d/%Y %H:%M", ltime);
}
return (string);
}
+/* compactDateString
+ * print out a date in compact format, 16 chars, format is
+ * mm/dd/yyyy hh:mm
+ * entry:
+ * date_long - ptr to a long containing the time
+ * exit:
+ * ptr to a string containing a representation of the date
+ */
+char *
+compactDateString(afs_uint32 *date_long, char *string, afs_int32 size)
+{
+ time_t t = *date_long;
+ return compactTimeString(&t, string, size);
+}
+
+
afs_int32
bc_SafeATOI(char *anum)
{
tlen = strlen(astring);
tp = (char *)malloc(tlen + 1); /* don't forget the terminating null */
if (!tp) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return (tp);
}
strcpy(tp, astring);
}
/* concatParams
- *
+ *
* Concatenates the parameters of an option and returns the string.
*
*/
string = (char *)malloc(length); /* allocate the string */
if (!string) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return (NULL);
}
string[0] = 0;
/* printIfStatus
* print out an interface status node as received from butc
*/
-
+
void
printIfStatus(struct tciStatusS *statusPtr)
{
if (statusPtr->dbDumpId)
printf(": DumpID %u", statusPtr->dbDumpId);
if (statusPtr->nKBytes)
- printf(", %ld Kbytes", afs_cast_int32(statusPtr->nKBytes));
+ printf(", %ld Kbytes", afs_printable_int32_ld(statusPtr->nKBytes));
if (strlen(statusPtr->volumeName) != 0)
printf(", volume %s", statusPtr->volumeName);
}
}
- /*
+ /*
* Now print the scheduled dumps.
*/
if (!dlqEmpty(&statusHead) && as)
}
/* Print token expiration time */
- if ((ttoken.endTime > prevTime)
- && (ttoken.endTime <= youngest->scheduledDump) && as
- && (ttoken.endTime != NEVERDATE)) {
- if (ttoken.endTime > time(0)) {
- compactDateString(&ttoken.endTime, ds, 50);
+ if ((tokenExpires > prevTime)
+ && (tokenExpires <= youngest->scheduledDump) && as
+ && (tokenExpires != NEVERDATE)) {
+ if (tokenExpires > time(0)) {
+ compactTimeString(&tokenExpires, ds, 50);
printf(" %16s: TOKEN EXPIRATION\n", ds);
} else {
printf(" TOKEN HAS EXPIRED\n");
}
/* Print token expiration time if havn't already */
- if ((ttoken.endTime == NEVERDATE) && as)
+ if ((tokenExpires == NEVERDATE) && as)
printf(" : TOKEN NEVER EXPIRES\n");
- else if ((ttoken.endTime > prevTime) && as) {
- if (ttoken.endTime > time(0)) {
- compactDateString(&ttoken.endTime, ds, 50);
+ else if ((tokenExpires > prevTime) && as) {
+ if (tokenExpires > time(0)) {
+ compactTimeString(&tokenExpires, ds, 50);
printf(" %16s: TOKEN EXPIRATION\n", ds);
} else {
printf(" : TOKEN HAS EXPIRED\n");
/* build list of volume items */
tvol = (struct bc_volumeDump *)malloc(sizeof(struct bc_volumeDump));
if (!tvol) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
memset(tvol, 0, sizeof(struct bc_volumeDump));
tvol->name = (char *)malloc(VOLSER_MAXVOLNAME + 1);
if (!tvol->name) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
strncpy(tvol->name, ti->data, VOLSER_OLDMAXVOLNAME);
oldFlag = 0;
/* Read all the port offsets into the ports array. The first element in the
- * array is for full restore and the rest are for incremental restores
+ * array is for full restore and the rest are for incremental restores
*/
if (as->parms[5].items) {
for (ti = as->parms[5].items; ti; ti = ti->next)
portCount++;
ports = (afs_int32 *) malloc(portCount * sizeof(afs_int32));
if (!ports) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
if (dumpID <= 0)
dumpID = 0;
}
-
+
/*
* Perform the call to start the restore.
*/
/* parm 0 is the server to restore
* parm 1 is the partition to restore
-
+
* parm 8 and above as in VolRestoreCmd:
* parm 8 is the new server to restore to
* parm 9 is the new partition to restore to
portCount++;
ports = (afs_int32 *) malloc(portCount * sizeof(afs_int32));
if (!ports) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
return (-1);
}
- /* Since we want only RW volumes, remove any
+ /* Since we want only RW volumes, remove any
* BK or RO volumes from the list.
*/
for (prev = 0, tvol = volsToRestore; tvol; tvol = nextvol) {
tvol->name = (char *)malloc(VOLSER_MAXVOLNAME + 1);
if (!tvol->name) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
strncpy(tvol->name, volume, VOLSER_OLDMAXVOLNAME);
portCount++;
ports = (afs_int32 *) malloc(portCount * sizeof(afs_int32));
if (!ports) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
afs_int32 problemFindingDump; /* can't find parent(s) */
afs_int32 *portp = NULL;
- afs_int32 portCount = 0;
afs_int32 doAt, atTime; /* Time a timed-dump is to start at */
afs_int32 length;
char *timeString;
return (code);
}
- /*
+ /*
* Some parameters cannot be specified together
- * The "-file" option cannot exist with the "-volume", "-dump",
- * "-portoffset", or "-append" option
+ * The "-file" option cannot exist with the "-volume", "-dump",
+ * "-portoffset", or "-append" option
*/
if (as->parms[6].items) {
loadfile = 1;
}
}
- /*
+ /*
* Get the time we are to perform this dump
*/
if (as->parms[3].items) {
dontExecute = (as->parms[5].items ? 1 : 0); /* -n */
- /*
+ /*
* If this dump is not a load file, then check the parameters.
*/
if (!loadfile) { /*6 */
/* get the port number, if one was specified */
if (as->parms[2].items) {
- portCount = 1;
portp = (afs_int32 *) malloc(sizeof(afs_int32));
if (!portp) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
/*6 */
/*
- * If given the "-at" option, then add this to the jobs list and return
+ * If given the "-at" option, then add this to the jobs list and return
* with no error.
*
* Create a status node for this timed dump.
* Fill in the time to dump and the cmd line for the dump leaving off
- * the -at option. If the -n option is there, it is scheduled with
+ * the -at option. If the -n option is there, it is scheduled with
* the Timed dump as opposed to not scheduling the time dump at all.
*/
if (doAt) {
statusPtr->scheduledDump = atTime;
statusPtr->cmdLine = (char *)malloc(length);
if (!statusPtr->cmdLine) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
strcat(statusPtr->cmdLine, " -n");
printf("Add scheduled dump as job %d\n", statusPtr->jobNumber);
- if ((atTime > ttoken.endTime) && (ttoken.endTime != NEVERDATE))
+ if ((atTime > tokenExpires) && (tokenExpires != NEVERDATE))
afs_com_err(whoami, 0,
"Warning: job %d starts after expiration of AFS token",
statusPtr->jobNumber);
return (0);
}
- /*
+ /*
* Read and execute the load file if specified. The work of reading is done
* in the main routine prior the dispatch call. loadFile and dontExecute are
* global variables so this can take place in main.
if (loadfile) {
loadFile = (char *)malloc(strlen(as->parms[6].items->data) + 1);
if (!loadFile) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
return BC_NOMEM;
}
strcpy(loadFile, as->parms[6].items->data);
return 0;
}
- /*
+ /*
* We are doing a real dump (no load file or timed dump).
*/
printf("Starting dump of volume set '%s' (dump level '%s')\n", vsName,
}
/* We found the most recent dump at this level. Now check
- * if we should use it by seeing if its full dump hierarchy
+ * if we should use it by seeing if its full dump hierarchy
* exists. If it doesn't, we don't want to base our incremental
- * off of this dump.
+ * off of this dump.
*/
if (!parent || (dumpEntry.id > parent)) {
/* Follow the parent dumps to see if they are all there */
}
}
- /* If the problemflag was raise, it means we are not doing the
+ /* If the problemflag was raise, it means we are not doing the
* dump at the level we requested it be done at.
*/
if (problemFindingDump) {
*/
afs_int32
-bc_ParseExpiration(struct cmd_parmdesc *paramPtr, afs_int32 *expType,
+bc_ParseExpiration(struct cmd_parmdesc *paramPtr, afs_int32 *expType,
afs_int32 *expDate)
{
struct cmd_item *itemPtr;
/* If dump is to an XBSA server, connect to butc and send it
* the dump to delete. Butc will contact the XBSA server.
- * The dump will not be an appended dump because XBSA butc
+ * The dump will not be an appended dump because XBSA butc
* does not support the append option.
*/
if (xbsadump && dumpEntry.nVolumes) {
/* Display the dumps that were deleted - includes appended dumps */
for (i = 0; i < dumps.budb_dumpsList_len; i++)
printf(" %u%s\n", dumps.budb_dumpsList_val[i],
- (i > 0) ? " Appended Dump" : "");
+ (i > 0) ? " Appended Dump" : NULL);
if (dumps.budb_dumpsList_val)
free(dumps.budb_dumpsList_val);
}
afs_int32 rcode = 0;
afs_int32 groupId = 0, havegroupid, sflags, noexecute;
struct cmd_item *ti;
- afs_uint32 fromTime = 0, toTime = 0, havetime = 0;
+ afs_int32 fromTime = 0, toTime = 0, havetime = 0;
char *timeString;
budb_dumpsList dumps, flags;
int i;
- afs_int32 port = -1, dbonly = 0, force;
+ afs_int32 port = -1, force;
/* Must specify at least one of -dumpid, -from, or -to */
if (!as->parms[0].items && !as->parms[1].items && !as->parms[2].items
}
/* ----------------------------------
- * supporting routines for database examination
+ * supporting routines for database examination
* ----------------------------------
*/
}
if (code)
- afs_com_err(whoami, code, "");
+ afs_com_err(whoami, code, NULL);
return (code);
}
for (tapeNumber = dumpEntry.tapes.b; tapeNumber <= dumpEntry.tapes.maxTapes; tapeNumber++) { /*f */
tapeLinkPtr = (struct tapeLink *)malloc(sizeof(struct tapeLink));
if (!tapeLinkPtr) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
ERROR(BC_NOMEM);
}
volumeLinkPtr =
(struct volumeLink *)malloc(sizeof(struct volumeLink));
if (!volumeLinkPtr) {
- afs_com_err(whoami, BC_NOMEM, "");
+ afs_com_err(whoami, BC_NOMEM, NULL);
ERROR(BC_NOMEM);
}
memset(volumeLinkPtr, 0, sizeof(*volumeLinkPtr));
return (code);
}
-/* bc_dumpInfoCmd
+/* bc_dumpInfoCmd
* list the dumps and contens of the dumps.
* params:
* as - name of tape