afs_int32 readDbTape(struct butm_tapeInfo *tapeInfoPtr, struct rstTapeInfo *rstTapeInfoPtr, int query) { afs_int32 code = 0; int interactiveFlag; afs_int32 taskId; struct butm_tapeLabel oldTapeLabel; char AFStapeName[BU_MAXTAPELEN], tapeName[BU_MAXTAPELEN]; struct tapeEntryList *endList; int tapecount = 1; struct budb_dumpEntry de; struct budb_tapeEntry te; taskId = rstTapeInfoPtr->taskId; interactiveFlag = query; /* construct the name of the tape */ sprintf(AFStapeName, "%s.%-d", DUMP_TAPE_NAME, rstTapeInfoPtr->tapeSeq); strcpy(tapeName, AFStapeName); /* Will prompt for the latest saved database tape, but will accept any one */ if (rstTapeInfoPtr->tapeSeq == 1) { code = bcdb_FindLatestDump("", "", &de); if (!code) rstTapeInfoPtr->dumpid = de.id; } if (rstTapeInfoPtr->dumpid) { code = bcdb_FindTapeSeq(rstTapeInfoPtr->dumpid, rstTapeInfoPtr->tapeSeq, &te); if (!code) strcpy(tapeName, te.name); } code = 0; while (1) { /*w */ if (interactiveFlag) { /* need a tape to read */ code = PromptForTape(RESTOREDBOPCODE, tapeName, rstTapeInfoPtr->dumpid, taskId, tapecount); if (code) ERROR_EXIT(code); } interactiveFlag = 1; tapecount++; code = butm_Mount(tapeInfoPtr, tapeName); if (code) { TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n"); goto getNewTape; } code = butm_ReadLabel(tapeInfoPtr, &oldTapeLabel, 1); /* will rewind the tape */ if (code) { TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't read tape label\n"); goto getNewTape; } /* Check for name of tape and matching dump id (if applicable). */ if ((strcmp(oldTapeLabel.AFSName, AFStapeName) != 0) || ((rstTapeInfoPtr->tapeSeq != 1) && (oldTapeLabel.dumpid != rstTapeInfoPtr->dumpid))) { char expTape[BU_MAXTAPELEN + 32]; char gotTape[BU_MAXTAPELEN + 32]; TAPENAME(expTape, tapeName, rstTapeInfoPtr->dumpid); TAPENAME(gotTape, oldTapeLabel.AFSName, oldTapeLabel.dumpid); TLog(taskId, "Tape label expected %s, label seen %s\n", expTape, gotTape); goto getNewTape; } if (rstTapeInfoPtr->tapeSeq == 1) /* Remember this dumpId */ rstTapeInfoPtr->dumpid = oldTapeLabel.dumpid; break; getNewTape: unmountTape(taskId, tapeInfoPtr); } /*w */ /* Initialize a tapeEntry for later inclusion into the database */ listEntryPtr = (struct tapeEntryList *)malloc(sizeof(struct tapeEntryList)); if (!listEntryPtr) ERROR_EXIT(TC_NOMEMORY); memset(listEntryPtr, 0, sizeof(struct tapeEntryList)); /* Fill in tape entry so we can save it later */ strcpy(tapeEntryPtr->name, TNAME(&oldTapeLabel)); tapeEntryPtr->dump = oldTapeLabel.dumpid; tapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN; tapeEntryPtr->written = oldTapeLabel.creationTime; tapeEntryPtr->expires = oldTapeLabel.expirationDate; tapeEntryPtr->seq = extractTapeSeq(oldTapeLabel.AFSName); tapeEntryPtr->useCount = oldTapeLabel.useCount; tapeEntryPtr->useKBytes = 0; tapeEntryPtr->labelpos = 0; /* Thread onto end of single-linked list */ if (listEntryHead) { endList = listEntryHead; while (endList->next) endList = endList->next; endList->next = listEntryPtr; } else listEntryHead = listEntryPtr; error_exit: return (code); }
static int WorkerBee(struct cmd_syndesc *as, void *arock) { afs_int32 code; struct rx_securityClass *(securityObjects[3]); struct rx_service *service; time_t tokenExpires; char cellName[64]; int localauth; /*process arguments */ afs_int32 portOffset = 0; #ifdef AFS_PTHREAD_ENV pthread_t dbWatcherPid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS dbWatcherPid; #endif afs_uint32 host = htonl(INADDR_ANY); debugLevel = 0; /*initialize the error tables */ initialize_KA_error_table(); initialize_RXK_error_table(); initialize_KTC_error_table(); initialize_ACFG_error_table(); initialize_CMD_error_table(); initialize_VL_error_table(); initialize_BUTM_error_table(); initialize_BUTC_error_table(); #ifdef xbsa initialize_BUTX_error_table(); #endif /*xbs */ initialize_VOLS_error_table(); initialize_BUDB_error_table(); initialize_BUCD_error_table(); if (as->parms[0].items) { portOffset = SafeATOL(as->parms[0].items->data); if (portOffset == -1) { fprintf(stderr, "Illegal port offset '%s'\n", as->parms[0].items->data); exit(1); } else if (portOffset > BC_MAXPORTOFFSET) { fprintf(stderr, "%u exceeds max port offset %u\n", portOffset, BC_MAXPORTOFFSET); exit(1); } } xbsaType = XBSA_SERVER_TYPE_NONE; /* default */ if (as->parms[3].items) { /* -device */ globalTapeConfig.capacity = 0x7fffffff; /* 2T for max tape capacity */ globalTapeConfig.fileMarkSize = 0; globalTapeConfig.portOffset = portOffset; strncpy(globalTapeConfig.device, as->parms[3].items->data, 100); xbsaType = XBSA_SERVER_TYPE_NONE; /* Not XBSA */ } else { /* Search for an entry in tapeconfig file */ code = GetDeviceConfig(tapeConfigFile, &globalTapeConfig, portOffset); if (code == -1) { fprintf(stderr, "Problem in reading config file %s\n", tapeConfigFile); exit(1); } /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so * it's an XBSA server. Don't know if its ADSM or not so its unknown. */ xbsaType = ((code == 1) ? XBSA_SERVER_TYPE_UNKNOWN : XBSA_SERVER_TYPE_NONE); } if (as->parms[6].items) { /* -restoretofile */ int s = strlen(as->parms[6].items->data); restoretofile = malloc(s + 1); strncpy(restoretofile, as->parms[6].items->data, s + 1); printf("Restore to file '%s'\n", restoretofile); } /* Go and read the config file: CFG_<device> or CFG_<port>. We will also set * the exact xbsaType within the call (won't be unknown) - double check. */ code = GetConfigParams(pFile, portOffset); if (code) exit(code); #ifdef xbsa if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) { printf ("\nConfiguration file error, the TYPE parameter must be specified, or\n"); printf("an entry must exist in %s for port %d\n", tapeConfigFile, portOffset); exit(1); } #else /* Not compiled for XBSA code so we can't support it */ if (CONF_XBSA) { printf("\nNo entry found in %s for port %d\n", tapeConfigFile, portOffset); printf("This binary does not have XBSA support\n"); exit(1); } #endif /* Open the log files. The pathnames were set in GetConfigParams() */ logIO = fopen(logFile, "a"); if (!logIO) { fprintf(stderr, "Failed to open %s\n", logFile); exit(1); } ErrorlogIO = fopen(ErrorlogFile, "a"); if (!ErrorlogIO) { fprintf(stderr, "Failed to open %s\n", ErrorlogFile); exit(1); } if (lastLog) { lastLogIO = fopen(lastLogFile, "a"); if (!lastLogIO) { fprintf(stderr, "Failed to open %s\n", lastLogFile); exit(1); } } if (centralLogFile) { struct stat sbuf; afs_int32 statcode; #ifndef AFS_NT40_ENV char path[AFSDIR_PATH_MAX]; #endif statcode = stat(centralLogFile, &sbuf); centralLogIO = fopen(centralLogFile, "a"); if (!centralLogIO) { fprintf(stderr, "Failed to open %s; error %d\n", centralLogFile, errno); exit(1); } #ifndef AFS_NT40_ENV /* Make sure it is not in AFS, has to have been created first */ if (!realpath(centralLogFile, path)) { fprintf(stderr, "Warning: can't determine real path of '%s' (%d)\n", centralLogFile, errno); } else { if (strncmp(path, "/afs/", 5) == 0) { fprintf(stderr, "The central log '%s' should not be in AFS\n", centralLogFile); exit(1); } } #endif /* Write header if created it */ if (statcode) { char *h1 = "TASK START DATE/TIME END DATE/TIME ELAPSED VOLUMESET\n"; char *h2 = "----- ------------------- ------------------- -------- ---------\n"; /* File didn't exist before so write the header lines */ fwrite(h1, strlen(h1), 1, centralLogIO); fwrite(h2, strlen(h2), 1, centralLogIO); fflush(centralLogIO); } } if (as->parms[1].items) { debugLevel = SafeATOL(as->parms[1].items->data); if (debugLevel == -1) { TLog(0, "Illegal debug level '%s'\n", as->parms[1].items->data); exit(1); } } #ifdef xbsa /* Setup XBSA library interface */ if (CONF_XBSA) { afs_int32 rc; rc = xbsa_MountLibrary(&butxInfo, xbsaType); if (rc != XBSA_SUCCESS) { TapeLog(0, 0, rc, 0, "Unable to mount the XBSA library\n"); return (1); } forcemultiple = (as->parms[7].items ? 1 : 0);/*-xbsaforcemultiple */ if (forcemultiple) printf("Force XBSA multiple server support\n"); rc = InitToServer(0 /*taskid */ , &butxInfo, adsmServerName); if (rc != XBSA_SUCCESS) return (1); } #endif /*xbsa */ /* cell switch */ if (as->parms[2].items) strncpy(cellName, as->parms[2].items->data, sizeof(cellName)); else cellName[0] = '\0'; if (as->parms[4].items) autoQuery = 0; localauth = (as->parms[5].items ? 1 : 0); rxBind = (as->parms[8].items ? 1 : 0); if (rxBind) { afs_int32 ccode; if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) { char reason[1024]; ccode = parseNetFiles(SHostAddrs, NULL, NULL, ADDRSPERSITE, reason, AFSDIR_SERVER_NETINFO_FILEPATH, AFSDIR_SERVER_NETRESTRICT_FILEPATH); } else { ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE); } if (ccode == 1) host = SHostAddrs[0]; } code = rx_InitHost(host, htons(BC_TAPEPORT + portOffset)); if (code) { TapeLog(0, 0, code, 0, "rx init failed on port %u\n", BC_TAPEPORT + portOffset); exit(1); } rx_SetRxDeadTime(150); /* Establish connection with the vldb server */ code = vldbClientInit(0, localauth, cellName, &cstruct, &tokenExpires); if (code) { TapeLog(0, 0, code, 0, "Can't access vldb\n"); return code; } strcpy(globalCellName, cellName); /*initialize the dumpNode list */ InitNodeList(portOffset); deviceLatch = (struct deviceSyncNode *)(malloc(sizeof(struct deviceSyncNode))); Lock_Init(&(deviceLatch->lock)); deviceLatch->flags = 0; /* initialize database support, volume support, and logs */ /* Create a single security object, in this case the null security * object, for unauthenticated connections, which will be used to control * security on connections made to this server */ securityObjects[0] = rxnull_NewServerSecurityObject(); securityObjects[1] = (struct rx_securityClass *)0; /* don't bother with rxvab */ if (!securityObjects[0]) { TLog(0, "rxnull_NewServerSecurityObject"); exit(1); } service = rx_NewServiceHost(host, 0, 1, "BUTC", securityObjects, 3, TC_ExecuteRequest); if (!service) { TLog(0, "rx_NewService"); exit(1); } rx_SetMaxProcs(service, 4); /* Establish connection to the backup database */ code = udbClientInit(0, localauth, cellName); if (code) { TapeLog(0, 0, code, 0, "Can't access backup database\n"); exit(1); } /* This call is here to verify that we are authentiated. * The call does nothing and will return BUDB_NOTPERMITTED * if we don't belong. */ code = bcdb_deleteDump(0, 0, 0, 0); if (code == BUDB_NOTPERMITTED) { TapeLog(0, 0, code, 0, "Can't access backup database\n"); exit(1); } initStatus(); #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) { TapeLog(0, 0, code, 0, "Can't pthread_attr_init database monitor task"); exit(1); } code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) { TapeLog(0, 0, code, 0, "Can't pthread_attr_setdetachstate database monitor task"); exit(1); } AFS_SIGSET_CLEAR(); code = pthread_create(&dbWatcherPid, &tattr, dbWatcher, (void *)2); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(dbWatcher, 20480, LWP_NORMAL_PRIORITY, (void *)2, "dbWatcher", &dbWatcherPid); #endif if (code) { TapeLog(0, 0, code, 0, "Can't create database monitor task"); exit(1); } TLog(0, "Starting Tape Coordinator: Port offset %u Debug level %u\n", portOffset, debugLevel); TLog(0, "Token expires: %s\n", cTIME(&tokenExpires)); rx_StartServer(1); /* Donate this process to the server process pool */ TLog(0, "Error: StartServer returned"); exit(1); }
/* GetDBTape * Load a DB tape, read and over write its label. * Leave the tape mounted. */ afs_int32 GetDBTape(afs_int32 taskId, Date expires, struct butm_tapeInfo *tapeInfoPtr, afs_uint32 dumpid, afs_int32 sequence, int queryFlag, int *wroteLabel) { afs_int32 code = 0; int interactiveFlag; char tapeName[BU_MAXTAPELEN]; char strlevel[5]; struct timeval tp; struct timezone tzp; afs_int32 curTime; int tapecount = 1; struct butm_tapeLabel oldTapeLabel, newLabel; struct tapeEntryList *endList; /* construct the name of the tape */ sprintf(tapeName, "%s.%-d", DUMP_TAPE_NAME, sequence); interactiveFlag = queryFlag; *wroteLabel = 0; while (!*wroteLabel) { /*w */ if (interactiveFlag) { /* need a tape to write */ code = PromptForTape(SAVEDBOPCODE, tapeName, dumpid, taskId, tapecount); if (code) ERROR_EXIT(code); } interactiveFlag = 1; tapecount++; code = butm_Mount(tapeInfoPtr, tapeName); if (code) { TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n"); goto getNewTape; } memset(&oldTapeLabel, 0, sizeof(oldTapeLabel)); code = butm_ReadLabel(tapeInfoPtr, &oldTapeLabel, 1); /* rewind tape */ if (code) { oldTapeLabel.useCount = 0; /* no label exists */ oldTapeLabel.structVersion = 0; strcpy(oldTapeLabel.pName, ""); } else { /* If tape has a name, it must be null or database tape name */ if (dump_namecheck && strcmp(oldTapeLabel.AFSName, "") && !databaseTape(oldTapeLabel.AFSName)) { char gotName[BU_MAXTAPELEN + 32]; LABELNAME(gotName, &oldTapeLabel); TLog(taskId, "This tape %s must be a database tape or NULL tape\n", gotName); getNewTape: unmountTape(taskId, tapeInfoPtr); continue; } /* Do not overwrite a tape that belongs to this dump */ if (oldTapeLabel.dumpid && (oldTapeLabel.dumpid == dumpid)) { ErrorLog(0, taskId, 0, 0, "Can't overwrite tape containing the dump in progress\n"); goto getNewTape; } /* On first tape, the savedb has not started yet, so the database is not locked * and we can therefore, access information from it. This is easier to do because * database dumps don't have appended dumps (nor appended). */ if (sequence == 1) { afs_uint32 dmp; struct budb_dumpEntry de, de2; /* Verify the tape has not expired * Early database dumps don't have a dumpid */ if (!tapeExpired(&oldTapeLabel)) { TLog(taskId, "This tape has not expired\n"); goto getNewTape; } /* Since the dumpset on this tape will be deleted from database, check if * any of the dumps in this dumpset are most-recent-dumps. */ for (dmp = oldTapeLabel.dumpid; dmp; dmp = de.appendedDumpID) { if (dmp == lastDump.id) { memcpy(&de, &lastDump, sizeof(de)); memcpy(&de2, &lastDump, sizeof(de2)); } else { code = bcdb_FindDumpByID(dmp, &de); if (code) break; sprintf(strlevel, "%d", de.level); code = bcdb_FindLatestDump(de.volumeSetName, strlevel, &de2); if (code) continue; } if (de.id == de2.id) { if (strcmp(DUMP_TAPE_NAME, de2.name) == 0) { ErrorLog(0, taskId, 0, 0, "Warning: Overwriting most recent dump %s (DumpID %u)\n", de.name, de.id); } else { ErrorLog(0, taskId, 0, 0, "Warning: Overwriting most recent dump of the '%s' volumeset: %s (DumpID %u)\n", de.volumeSetName, de.name, de.id); } } } } /* Otherwise, the savedb is in progress and we can't * access the database (it's locked). So we rely on the * information available (and not the backup database). */ else { /* Check the tape's expiration date. Use the expiration on the label */ gettimeofday(&tp, &tzp); curTime = tp.tv_sec; if (curTime < oldTapeLabel.expirationDate) { TLog(taskId, "This tape has not expired\n"); goto getNewTape; } /* Check if this previous-dump of the dump-in-progress is on this tape */ if (oldTapeLabel.dumpid && (oldTapeLabel.dumpid == lastDump.id)) { ErrorLog(0, taskId, 0, 0, "Warning: Overwriting most recent dump %s (DumpID %u)\n", lastDump.name, lastDump.id); } } } GetNewLabel(tapeInfoPtr, oldTapeLabel.pName, tapeName, &newLabel); newLabel.expirationDate = expires; newLabel.useCount = oldTapeLabel.useCount + 1; newLabel.dumpid = dumpid; newLabel.size = tapeInfoPtr->tapeSize; code = butm_Create(tapeInfoPtr, &newLabel, 1); /* rewind tape */ if (code) { TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't label tape\n"); goto getNewTape; } *wroteLabel = 1; /* Initialize a tapeEntry for later inclusion into the database */ listEntryPtr = (struct tapeEntryList *)malloc(sizeof(struct tapeEntryList)); if (!listEntryPtr) ERROR_EXIT(TC_NOMEMORY); memset(listEntryPtr, 0, sizeof(struct tapeEntryList)); /* Remember dumpid so we can delete it later */ if ((oldTapeLabel.structVersion >= TAPE_VERSION_3) && oldTapeLabel.dumpid) listEntryPtr->oldDumpId = oldTapeLabel.dumpid; /* Fill in tape entry so we can save it later */ strcpy(tapeEntryPtr->name, TNAME(&newLabel)); tapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN; tapeEntryPtr->written = newLabel.creationTime; tapeEntryPtr->expires = expires; tapeEntryPtr->seq = sequence; tapeEntryPtr->useCount = oldTapeLabel.useCount + 1; tapeEntryPtr->dump = dumpid; tapeEntryPtr->useKBytes = 0; tapeEntryPtr->labelpos = 0; /* Thread onto end of single-linked list */ if (listEntryHead) { endList = listEntryHead; while (endList->next) endList = endList->next; endList->next = listEntryPtr; } else listEntryHead = listEntryPtr; } /*w */ error_exit: return (code); }
void * saveDbToTape(void *param) { struct saveDbIf *saveDbIfPtr = (struct saveDbIf *)param; afs_int32 code = 0; afs_int32 i; int wroteLabel; afs_uint32 taskId; Date expires; struct butm_tapeInfo tapeInfo; struct budb_dumpEntry dumpEntry; extern struct deviceSyncNode *deviceLatch; extern struct tapeConfig globalTapeConfig; expires = (saveDbIfPtr->archiveTime ? NEVERDATE : 0); taskId = saveDbIfPtr->taskId; setStatus(taskId, DRIVE_WAIT); EnterDeviceQueue(deviceLatch); /* lock tape device */ clearStatus(taskId, DRIVE_WAIT); printf("\n\n"); TLog(taskId, "SaveDb\n"); tapeInfo.structVersion = BUTM_MAJORVERSION; code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig); if (code) { ErrorLog(0, taskId, code, tapeInfo.error, "Can't initialize tape module\n"); ERROR_EXIT(code); } /* Determine what the last database dump was */ memset(&lastDump, 0, sizeof(lastDump)); code = bcdb_FindLatestDump("", "", &lastDump); if (code) { if (code != BUDB_NODUMPNAME) { ErrorLog(0, taskId, code, 0, "Can't read backup database\n"); ERROR_EXIT(code); } memset(&lastDump, 0, sizeof(lastDump)); } code = CreateDBDump(&dumpEntry); /* Create a dump for this tape */ if (code) { ErrorLog(0, taskId, code, 0, "Can't create dump in database\n"); ERROR_EXIT(code); } listEntryHead = NULL; /* Get the tape and write a new label to it */ code = GetDBTape(taskId, expires, &tapeInfo, dumpEntry.id, 1, autoQuery, &wroteLabel); /* * If did not write the label, remove created dump * Else if wrote the label, remove old dump from db so it's not saved. */ if (!wroteLabel) { i = bcdb_deleteDump(dumpEntry.id, 0, 0, 0); dumpEntry.id = 0; if (i && (i != BUDB_NOENT)) ErrorLog(0, taskId, i, 0, "Unable to delete DB entry %u.\n", dumpEntry.id); } else if (listEntryHead->oldDumpId) { i = bcdb_deleteDump(listEntryHead->oldDumpId, 0, 0, 0); listEntryHead->oldDumpId = 0; if (i && (i != BUDB_NOENT)) { ErrorLog(0, taskId, i, 0, "Unable to delete old DB entry %u.\n", listEntryHead->oldDumpId); ERROR_EXIT(i); } } if (code) ERROR_EXIT(code); TapeLog(1, taskId, 0, 0, "Tape accepted - now dumping database\n"); /* we have a writable tape */ code = writeDbDump(&tapeInfo, taskId, expires, dumpEntry.id); if (code) ERROR_EXIT(code); /* Now delete the entries between time 0 and archive-time */ if (saveDbIfPtr->archiveTime) code = bcdb_deleteDump(0, 0, saveDbIfPtr->archiveTime, 0); error_exit: unmountTape(taskId, &tapeInfo); /* Add this dump's tapes to the database and mark it finished */ if (dumpEntry.id) { i = addTapesToDb(taskId); if (!code) code = i; i = bcdb_FinishDump(&dumpEntry); if (!code) code = i; } freeTapeList(); if (code == TC_ABORTEDBYREQUEST) { TLog(taskId, "SaveDb: Aborted by request\n"); clearStatus(taskId, ABORT_REQUEST); setStatus(taskId, ABORT_DONE); } else if (code) { TapeLog(0, taskId, code, 0, "SaveDb: Finished with errors\n"); setStatus(taskId, TASK_ERROR); } else { TLog(taskId, "SaveDb: Finished\n"); } setStatus(taskId, TASK_DONE); free(saveDbIfPtr); LeaveDeviceQueue(deviceLatch); return (void *)(intptr_t)(code); }
void * restoreDbFromTape(void *param) { afs_uint32 taskId = (intptr_t) param; afs_int32 code = 0; afs_int32 i; struct butm_tapeInfo tapeInfo; struct rstTapeInfo rstTapeInfo; struct budb_dumpEntry dumpEntry; extern struct tapeConfig globalTapeConfig; extern struct deviceSyncNode *deviceLatch; setStatus(taskId, DRIVE_WAIT); EnterDeviceQueue(deviceLatch); /* lock tape device */ clearStatus(taskId, DRIVE_WAIT); printf("\n\n"); TLog(taskId, "RestoreDb\n"); tapeInfo.structVersion = BUTM_MAJORVERSION; code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig); if (code) { ErrorLog(0, taskId, code, tapeInfo.error, "Can't initialize tape module\n"); ERROR_EXIT(code); } listEntryHead = NULL; rstTapeInfo.taskId = taskId; rstTapeInfo.tapeSeq = 1; rstTapeInfo.dumpid = 0; code = readDbTape(&tapeInfo, &rstTapeInfo, autoQuery); if (code) ERROR_EXIT(code); code = restoreDbEntries(&tapeInfo, &rstTapeInfo); if (code) ERROR_EXIT(code); error_exit: /* Now put this dump into the database */ /* Make a dump entry from first tape */ listEntryPtr = listEntryHead; if (listEntryPtr) { makeDbDumpEntry(tapeEntryPtr, &dumpEntry); if (dumpEntry.id != 0) { i = bcdb_CreateDump(&dumpEntry); if (i) { if (i == BUDB_DUMPIDEXISTS) fprintf(stderr, "Dump id %d not added to database - already exists\n", dumpEntry.id); else TapeLog(0, taskId, i, 0, "Dump id %d not added to database\n", dumpEntry.id); } else { i = addTapesToDb(taskId); if (!code) code = i; i = bcdb_FinishDump(&dumpEntry); if (!code) code = i; } } freeTapeList(); } unmountTape(taskId, &tapeInfo); waitDbWatcher(); if (code == TC_ABORTEDBYREQUEST) { TLog(taskId, "RestoreDb: Aborted by request\n"); clearStatus(taskId, ABORT_REQUEST); setStatus(taskId, ABORT_DONE); } else if (code) { TapeLog(0, taskId, code, 0, "RestoreDb: Finished with errors\n"); setStatus(taskId, TASK_ERROR); } else { TLog(taskId, "RestoreDb: Finished\n"); } LeaveDeviceQueue(deviceLatch); setStatus(taskId, TASK_DONE); return (void *)(intptr_t)(code); }
afs_int32 getScanTape(afs_int32 taskId, struct butm_tapeInfo *tapeInfoPtr, char *tname, afs_int32 tapeId, int prompt, struct butm_tapeLabel *tapeLabelPtr) { afs_int32 code = 0; int tapecount = 1; afs_int32 curseq; char tapename[BU_MAXTAPELEN + 32]; char gotname[BU_MAXTAPELEN + 32]; while (1) { /* prompt for a tape */ if (prompt) { code = PromptForTape(SCANOPCODE, tname, tapeId, taskId, tapecount); if (code) ERROR_EXIT(code); } prompt = 1; tapecount++; code = butm_Mount(tapeInfoPtr, ""); /* open the tape device */ if (code) { TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n"); goto newtape; } /* read the label on the tape */ code = butm_ReadLabel(tapeInfoPtr, tapeLabelPtr, 1); /* rewind tape */ if (code) { ErrorLog(0, taskId, code, tapeInfoPtr->error, "Can't read tape label\n"); goto newtape; } tapepos = tapeInfoPtr->position - 1; /* Now check that the tape is good */ TAPENAME(tapename, tname, tapeId); TAPENAME(gotname, tapeLabelPtr->AFSName, tapeLabelPtr->dumpid); curseq = extractTapeSeq(tapeLabelPtr->AFSName); /* Label can't be null or a bad name */ if (!strcmp(tapeLabelPtr->AFSName, "") || (curseq <= 0)) { TLog(taskId, "Expected tape with dump, label seen %s\n", gotname); goto newtape; } /* Label can't be a database tape */ if (databaseTape(tapeLabelPtr->AFSName)) { TLog(taskId, "Expected tape with dump. Can't scan database tape %s\n", gotname); goto newtape; } /* If no name, accept any tape */ if (strcmp(tname, "") == 0) { break; /* Start scan on any tape */ #ifdef notdef if (curseq == 1) break; /* The first tape */ else { TLog(taskId, "Expected first tape of dump, label seen %s\n", gotname); goto newtape; } #endif } if (strcmp(tname, tapeLabelPtr->AFSName) || ((tapeLabelPtr->structVersion >= TAPE_VERSION_3) && (tapeLabelPtr->dumpid != tapeId))) { TLog(taskId, "Tape label expected %s, label seen %s\n", tapename, gotname); goto newtape; } /* We have the correct tape */ break; newtape: unmountTape(taskId, tapeInfoPtr); } error_exit: return (code); }
static int readDump(afs_uint32 taskId, struct butm_tapeInfo *tapeInfoPtr, struct tapeScanInfo *scanInfoPtr) { int moreTapes = 1; afs_int32 flags, seq; afs_uint32 nbytes = 0; int newDump = 1, newTape = 1; afs_int32 tapePosition; afs_int32 code = 0, tcode; int badscan; struct volumeHeader volHeader, volTrailer; struct budb_tapeEntry tapeEntry; struct budb_volumeEntry volEntry; volEntry.dump = 0; PrintDumpLabel(&scanInfoPtr->dumpLabel); while (moreTapes) { /* While there is a tape to read *//*t */ badscan = 0; while (1) { /* Read each volume on the tape *//*w */ moreTapes = -1; tapePosition = tapeInfoPtr->position; /* remember position */ /* * Skip the volume data */ tcode = scanVolData(taskId, tapeInfoPtr, scanInfoPtr->tapeLabel.structVersion, &volHeader, &volTrailer, &nbytes); if (tcode) { badscan++; if (tcode == TC_ABORTEDBYREQUEST) { /* Aborted */ ERROR_EXIT(tcode); } if (tcode == BUTM_EOD) { moreTapes = 0; /* the end of the dump */ break; } /* Found a volume but it's incomplete. Skip over these */ if (volHeader.volumeID) { TapeLog(0, taskId, tcode, 0, "Warning: volume %s (%u) ignored. Incomplete\n", volHeader.volumeName, volHeader.volumeID); continue; } /* No volume was found. We may have hit the EOT or a * bad-spot. Try to skip over this spot. */ if (badscan < 2) { /* allow 2 errors, then fail */ TapeLog(0, taskId, tcode, 0, "Warning: Error in scanning tape - will try skipping volume\n"); continue; } if (scanInfoPtr->tapeLabel.structVersion >= TAPE_VERSION_4) { TapeLog(0, taskId, tcode, 0, "Warning: Error in scanning tape - end-of-tape inferred\n"); moreTapes = 1; /* then assume next tape */ } else { ErrorLog(0, taskId, tcode, 0, "Error in scanning tape\n"); /* will ask if there is a next tape */ } break; } PrintVolumeHeader(&volHeader); /* If this is not the first volume fragment, make sure it follows * the last volume fragment */ if (volEntry.dump) { if ((volEntry.dump != volHeader.dumpID) || (volEntry.id != volHeader.volumeID) || (volEntry.seq != volHeader.frag - 2) || (strcmp(volEntry.name, volHeader.volumeName))) { TLog(taskId, "Warning: volume %s (%u) ignored. Incomplete - no last fragment\n", volEntry.name, volEntry.id); if (scanInfoPtr->addDbFlag) { tcode = flushSavedEntries(DUMP_FAILED); if (tcode) ERROR_EXIT(tcode); volEntry.dump = 0; } } } /* If this is the first volume fragment, make sure says so */ if (scanInfoPtr->addDbFlag && !volEntry.dump && (volHeader.frag != 1)) { TLog(taskId, "Warning: volume %s (%u) ignored. Incomplete - no first fragment\n", volHeader.volumeName, volHeader.volumeID); } /* Check that this volume belongs to the dump we are scanning */ else if (scanInfoPtr->dumpLabel.dumpid && (volHeader.dumpID != scanInfoPtr->dumpLabel.dumpid)) { TLog(taskId, "Warning: volume %s (%u) ignored. Expected DumpId %u, got %u\n", volHeader.volumeName, volHeader.volumeID, scanInfoPtr->dumpLabel.dumpid, volHeader.dumpID); } /* Passed tests, Now add to the database (if dbadd flag is set) */ else if (scanInfoPtr->addDbFlag) { /* Have enough information to create a dump entry */ if (newDump) { tcode = RcreateDump(scanInfoPtr, &volHeader); if (tcode) { ErrorLog(0, taskId, tcode, 0, "Can't add dump %u to database\n", volHeader.dumpID); ERROR_EXIT(tcode); } newDump = 0; } /* Have enough information to create a tape entry */ if (newTape) { seq = extractTapeSeq(scanInfoPtr->tapeLabel.AFSName); if (seq < 0) ERROR_EXIT(TC_INTERNALERROR); tcode = useTape(&tapeEntry, volHeader.dumpID, TNAME(&scanInfoPtr->tapeLabel), seq, scanInfoPtr->tapeLabel.useCount, scanInfoPtr->dumpLabel.creationTime, scanInfoPtr->dumpLabel.expirationDate, tapepos); if (tcode) { char gotName[BU_MAXTAPELEN + 32]; LABELNAME(gotName, &scanInfoPtr->tapeLabel); ErrorLog(0, taskId, tcode, 0, "Can't add tape %s for dump %u to database\n", gotName, volHeader.dumpID); ERROR_EXIT(tcode); } newTape = 0; } /* Create the volume entry */ flags = ((volHeader.frag == 1) ? BUDB_VOL_FIRSTFRAG : 0); if (!volTrailer.contd) flags |= BUDB_VOL_LASTFRAG; tcode = addVolume(&volEntry, volHeader.dumpID, TNAME(&scanInfoPtr->tapeLabel), volHeader.volumeName, volHeader.volumeID, volHeader.cloneDate, tapePosition, nbytes, (volHeader.frag - 1), flags); if (tcode) { ErrorLog(0, taskId, tcode, 0, "Can't add volume %s (%u) for dump %u to database\n", volHeader.volumeName, volHeader.volumeID, volHeader.dumpID); ERROR_EXIT(tcode); } } if (volTrailer.contd) { /* No need to read the EOD marker, we know there is a next tape */ moreTapes = 1; break; } else { if (scanInfoPtr->addDbFlag) { tcode = flushSavedEntries(DUMP_SUCCESS); if (tcode) ERROR_EXIT(tcode); volEntry.dump = 0; } } } /*w */ if (!newTape) { if (scanInfoPtr->addDbFlag) { tcode = finishTape(&tapeEntry, (tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0))); if (tcode) { char gotName[BU_MAXTAPELEN + 32]; LABELNAME(gotName, &scanInfoPtr->tapeLabel); ErrorLog(0, taskId, tcode, 0, "Can't mark tape %s 'completed' for dump %u in database\n", gotName, tapeEntry.dump); ERROR_EXIT(tcode); } } } /* Ask if there is another tape if we can't figure it out */ if (moreTapes == -1) moreTapes = (queryoperator ? Ask("Are there more tapes") : 1); /* Get the next tape label */ if (moreTapes) { char *tapeName; afs_int32 dumpid; unmountTape(taskId, tapeInfoPtr); tapeName = nextTapeLabel(scanInfoPtr->tapeLabel.AFSName); dumpid = scanInfoPtr->tapeLabel.dumpid; tcode = getScanTape(taskId, tapeInfoPtr, tapeName, dumpid, 1, &scanInfoPtr->tapeLabel); if (tcode) ERROR_EXIT(tcode); newTape = 1; } } /*t */ if (!newDump) { if (scanInfoPtr->addDbFlag) { tcode = finishDump(&scanInfoPtr->dumpEntry); if (tcode) { ErrorLog(0, taskId, tcode, 0, "Can't mark dump %u 'completed' in database\n", scanInfoPtr->dumpEntry.id); } tcode = flushSavedEntries(DUMP_SUCCESS); if (tcode) ERROR_EXIT(tcode); } } error_exit: return (code); }
static int scanVolData(afs_int32 taskId, struct butm_tapeInfo *curTapePtr, afs_int32 tapeVersion, struct volumeHeader *volumeHeader, struct volumeHeader *volumeTrailer, afs_uint32 *bytesRead) { afs_int32 headBytes, tailBytes; char *block = NULL; char *buffer[2]; int hasdata[2], curr, prev; afs_uint32 chunkSize = 0; afs_int32 nbytes; afs_int32 code = 0; afs_int32 rcode, tcode; memset(volumeHeader, 0, sizeof(struct volumeHeader)); block = (char *)malloc(2 * BUTM_BLOCKSIZE); if (!block) return (TC_NOMEMORY); buffer[0] = &block[sizeof(struct blockMark)]; buffer[1] = &block[BUTM_BLOCKSIZE + sizeof(struct blockMark)]; hasdata[0] = hasdata[1] = 0; curr = 0; tcode = NextFile(curTapePtr); /* guarantees we are at a filemark */ if (tcode) ERROR_EXIT(tcode) /* Read the FileBegin FileMark */ code = butm_ReadFileBegin(curTapePtr); if (code) { /* * Tapes made with 3.0 have no software EOT markers. Therefore * at this point, we will most likely get a read error, indicating * the end of this dump */ if ((tapeVersion == TAPE_VERSION_0) || (tapeVersion == TAPE_VERSION_1)) { /* * then a tape error is possible at this point, and it * signals the end of the dump. Tapes that are continued * have an EOT marker. */ TapeLog(0, taskId, code, curTapePtr->error, "Read error - end-of-dump inferred\n"); code = BUTM_EOD; } if (code != BUTM_EOD) ErrorLog(0, taskId, code, curTapePtr->error, "Can't read FileBegin on tape\n"); ERROR_EXIT(code); } /* now read the volume header */ code = ReadVolHeader(taskId, curTapePtr, volumeHeader); if (code) ERROR_EXIT(code); *bytesRead = 0; while (1) { /*w */ /* Check for abort in the middle of scanning data */ if (*bytesRead >= chunkSize) { if (checkAbortByTaskId(taskId)) ERROR_EXIT(TC_ABORTEDBYREQUEST); chunkSize += BIGCHUNK; } /* * Read volume date - If prematurely hit the HW EOF * marker, check to see if data contains a volumetrailer. */ rcode = butm_ReadFileData(curTapePtr, buffer[curr], BUTM_BLKSIZE, &nbytes); if (rcode) { hasdata[curr] = 0; if ((rcode == BUTM_EOF) || (rcode == BUTM_ENDVOLUME)) break; ErrorLog(0, taskId, rcode, curTapePtr->error, "Can't read FileData on tape\n"); ERROR_EXIT(rcode) } hasdata[curr] = 1; *bytesRead += nbytes; if ((nbytes != BUTM_BLKSIZE) || (FindVolTrailer(buffer[curr], nbytes, &tailBytes, volumeTrailer))) break; curr = ((curr == 0) ? 1 : 0); /* Switch buffers */ } /*w */ /* Now verify that there is a volume trailer and its valid and copy it */ prev = ((curr == 0) ? 1 : 0); if (!FindVolTrailer2 (buffer[prev], (hasdata[prev] ? BUTM_BLKSIZE : 0), &headBytes, buffer[curr], nbytes, &tailBytes, volumeTrailer)) { code = TC_MISSINGTRAILER; ErrorLog(0, taskId, code, 0, "Missing volume trailer on tape\n"); } else { /* subtract size of the volume trailer from data read */ *bytesRead -= sizeof(struct volumeHeader); } /* * If we didn't hit the EOF while reading data, read FileEnd marker * or EOF marker. */ if (!rcode) { tcode = butm_ReadFileEnd(curTapePtr); if (tcode) { ErrorLog(0, taskId, tcode, curTapePtr->error, "Can't read EOF on tape\n"); ERROR_EXIT(tcode); } } error_exit: if (block) free(block); return (code); }
static int WorkerBee(struct cmd_syndesc *as, void *arock) { afs_int32 code, numClasses; struct rx_securityClass *(nullObjects[1]), **secObjs, **allObjs; struct rx_service *service; time_t tokenExpires; char cellName[64]; int localauth; /*process arguments */ afs_int32 portOffset = 0; #ifdef AFS_PTHREAD_ENV pthread_t dbWatcherPid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS dbWatcherPid; #endif char hoststr[16]; afs_uint32 host = htonl(INADDR_ANY); char *auditFileName = NULL; char *auditInterface = NULL; debugLevel = 0; /*initialize the error tables */ initialize_KA_error_table(); initialize_RXK_error_table(); initialize_KTC_error_table(); initialize_ACFG_error_table(); initialize_CMD_error_table(); initialize_VL_error_table(); initialize_BUTM_error_table(); initialize_BUTC_error_table(); #ifdef xbsa initialize_BUTX_error_table(); #endif /*xbs */ initialize_VOLS_error_table(); initialize_BUDB_error_table(); initialize_BUCD_error_table(); if (as->parms[0].items) { portOffset = SafeATOL(as->parms[0].items->data); if (portOffset == -1) { fprintf(stderr, "Illegal port offset '%s'\n", as->parms[0].items->data); exit(1); } else if (portOffset > BC_MAXPORTOFFSET) { fprintf(stderr, "%u exceeds max port offset %u\n", portOffset, BC_MAXPORTOFFSET); exit(1); } } xbsaType = XBSA_SERVER_TYPE_NONE; /* default */ if (as->parms[3].items) { /* -device */ globalTapeConfig.capacity = 0x7fffffff; /* 2T for max tape capacity */ globalTapeConfig.fileMarkSize = 0; globalTapeConfig.portOffset = portOffset; strncpy(globalTapeConfig.device, as->parms[3].items->data, 100); xbsaType = XBSA_SERVER_TYPE_NONE; /* Not XBSA */ } else { /* Search for an entry in tapeconfig file */ code = GetDeviceConfig(tapeConfigFile, &globalTapeConfig, portOffset); if (code == -1) { fprintf(stderr, "Problem in reading config file %s\n", tapeConfigFile); exit(1); } /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so * it's an XBSA server. Don't know if its ADSM or not so its unknown. */ xbsaType = ((code == 1) ? XBSA_SERVER_TYPE_UNKNOWN : XBSA_SERVER_TYPE_NONE); } if (as->parms[6].items) { /* -restoretofile */ restoretofile = strdup(as->parms[6].items->data); printf("Restore to file '%s'\n", restoretofile); } /* Go and read the config file: CFG_<device> or CFG_<port>. We will also set * the exact xbsaType within the call (won't be unknown) - double check. */ code = GetConfigParams(pFile, portOffset); if (code) exit(code); #ifdef xbsa if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) { printf ("\nConfiguration file error, the TYPE parameter must be specified, or\n"); printf("an entry must exist in %s for port %d\n", tapeConfigFile, portOffset); exit(1); } #else /* Not compiled for XBSA code so we can't support it */ if (CONF_XBSA) { printf("\nNo entry found in %s for port %d\n", tapeConfigFile, portOffset); printf("This binary does not have XBSA support\n"); exit(1); } #endif /* Open the log files. The pathnames were set in GetConfigParams() */ logIO = fopen(logFile, "a"); if (!logIO) { fprintf(stderr, "Failed to open %s\n", logFile); exit(1); } ErrorlogIO = fopen(ErrorlogFile, "a"); if (!ErrorlogIO) { fprintf(stderr, "Failed to open %s\n", ErrorlogFile); exit(1); } if (lastLog) { lastLogIO = fopen(lastLogFile, "a"); if (!lastLogIO) { fprintf(stderr, "Failed to open %s\n", lastLogFile); exit(1); } } if (centralLogFile) { struct stat sbuf; afs_int32 statcode; #ifndef AFS_NT40_ENV char *path; #endif statcode = stat(centralLogFile, &sbuf); centralLogIO = fopen(centralLogFile, "a"); if (!centralLogIO) { fprintf(stderr, "Failed to open %s; error %d\n", centralLogFile, errno); exit(1); } #ifndef AFS_NT40_ENV /* Make sure it is not in AFS, has to have been created first */ path = malloc(AFSDIR_PATH_MAX); if (path == NULL || !realpath(centralLogFile, path)) { fprintf(stderr, "Warning: can't determine real path of '%s' (%d)\n", centralLogFile, errno); } else { if (strncmp(path, "/afs/", 5) == 0) { fprintf(stderr, "The central log '%s' should not be in AFS\n", centralLogFile); exit(1); } } free(path); #endif /* Write header if created it */ if (statcode) { char *h1 = "TASK START DATE/TIME END DATE/TIME ELAPSED VOLUMESET\n"; char *h2 = "----- ------------------- ------------------- -------- ---------\n"; /* File didn't exist before so write the header lines */ fwrite(h1, strlen(h1), 1, centralLogIO); fwrite(h2, strlen(h2), 1, centralLogIO); fflush(centralLogIO); } } /* Open the configuration directory */ butc_confdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH); if (butc_confdir == NULL) { TLog(0, "Failed to open server configuration directory"); exit(1); } /* Start auditing */ osi_audit_init(); if (as->parms[9].items) { auditFileName = as->parms[9].items->data; } if (auditFileName != NULL) osi_audit_file(auditFileName); if (as->parms[10].items) { auditInterface = as->parms[10].items->data; if (osi_audit_interface(auditInterface)) { TLog(0, "Invalid audit interface '%s'\n", auditInterface); exit(1); } } osi_audit(TC_StartEvent, 0, AUD_END); osi_audit_set_user_check(butc_confdir, tc_IsLocalRealmMatch); if (as->parms[1].items) { debugLevel = SafeATOL(as->parms[1].items->data); if (debugLevel == -1) { TLog(0, "Illegal debug level '%s'\n", as->parms[1].items->data); exit(1); } } #ifdef xbsa /* Setup XBSA library interface */ if (CONF_XBSA) { afs_int32 rc; rc = xbsa_MountLibrary(&butxInfo, xbsaType); if (rc != XBSA_SUCCESS) { TapeLog(0, 0, rc, 0, "Unable to mount the XBSA library\n"); return (1); } forcemultiple = (as->parms[7].items ? 1 : 0);/*-xbsaforcemultiple */ if (forcemultiple) printf("Force XBSA multiple server support\n"); rc = InitToServer(0 /*taskid */ , &butxInfo, adsmServerName); if (rc != XBSA_SUCCESS) return (1); (void)signal(SIGINT, xbsa_shutdown); (void)signal(SIGHUP, xbsa_shutdown); } #endif /*xbsa */ /* cell switch */ if (as->parms[2].items) strncpy(cellName, as->parms[2].items->data, sizeof(cellName)); else cellName[0] = '\0'; if (as->parms[4].items) autoQuery = 0; localauth = (as->parms[5].items ? 1 : 0); rxBind = (as->parms[8].items ? 1 : 0); allow_unauth = (as->parms[11].items ? 1 : 0); if (!allow_unauth && !localauth) { const char *errstr = "Neither -localauth nor -allow_unauthenticated was provided; refusing to start in unintended insecure configuration\n"; TLog(0, "%s", (char *)errstr); exit(1); } if (rxBind) { afs_int32 ccode; if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) { char reason[1024]; ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL, ADDRSPERSITE, reason, AFSDIR_SERVER_NETINFO_FILEPATH, AFSDIR_SERVER_NETRESTRICT_FILEPATH); } else { ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE); } if (ccode == 1) host = SHostAddrs[0]; } TLog(0, "butc binding rx to %s:%d\n", afs_inet_ntoa_r(host, hoststr), BC_TAPEPORT + portOffset); code = rx_InitHost(host, htons(BC_TAPEPORT + portOffset)); if (code) { TapeLog(0, 0, code, 0, "rx init failed on port %u\n", BC_TAPEPORT + portOffset); exit(1); } rx_SetRxDeadTime(150); /* Establish connection with the vldb server */ code = vldbClientInit(0, localauth, cellName, &cstruct, &tokenExpires); if (code) { TapeLog(0, 0, code, 0, "Can't access vldb\n"); return code; } strcpy(globalCellName, cellName); /*initialize the dumpNode list */ InitNodeList(portOffset); deviceLatch = malloc(sizeof(struct deviceSyncNode)); Lock_Init(&(deviceLatch->lock)); deviceLatch->flags = 0; /* initialize database support, volume support, and logs */ /* * Create security objects for the Rx server functionality. Historically * this was a single rxnull security object, since the tape controller was * run by an operator that had local access to the tape device and some * administrative privilege in the cell (to be able to perform volume-level * accesses), but on a machine that was not necessarily trusted to hold the * cell-wide key. * * Such a configuration is, of course, insecure because anyone can make * inbound RPCs and manipulate the database, including creating bogus * dumps and restoring them! Additionally, in modern usage, butc is * frequently run with -localauth to authenticate its outbound connections * to the volservers and budb with the cell-wide key, in which case the * cell-wide key is present and could be used to authenticate incoming * connections as well. * * If -localauth is in use, create the full barrage of server security * objects, including rxkad, so that inbound connections can be verified * to only be made by authenticated clients. Otherwise, only the rxnull * class is in use with a single server security object. Note that butc * will refuse to start in this configuration unless the * "-allow_unauthenticated" flag is provided, indicating that the operator * has ensured that incoming connections are appropriately restricted by * firewall configuration or network topology. */ if (allow_unauth) { nullObjects[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject(); if (!nullObjects[RX_SECIDX_NULL]) { TLog(0, "rxnull_NewServerSecurityObject"); exit(1); } numClasses = 1; secObjs = nullObjects; } else { /* Must be -localauth, so the cell keys are available. */ afsconf_BuildServerSecurityObjects(butc_confdir, &allObjs, &numClasses); secObjs = allObjs; } service = rx_NewServiceHost(host, 0, 1, "BUTC", secObjs, numClasses, TC_ExecuteRequest); if (!service) { TLog(0, "rx_NewService"); exit(1); } rx_SetMaxProcs(service, 4); /* Establish connection to the backup database */ code = udbClientInit(0, localauth, cellName); if (code) { TapeLog(0, 0, code, 0, "Can't access backup database\n"); exit(1); } /* This call is here to verify that we are authentiated. * The call does nothing and will return BUDB_NOTPERMITTED * if we don't belong. */ code = bcdb_deleteDump(0, 0, 0, 0); if (code == BUDB_NOTPERMITTED) { TapeLog(0, 0, code, 0, "Can't access backup database\n"); exit(1); } initStatus(); #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) { TapeLog(0, 0, code, 0, "Can't pthread_attr_init database monitor task"); exit(1); } code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) { TapeLog(0, 0, code, 0, "Can't pthread_attr_setdetachstate database monitor task"); exit(1); } AFS_SIGSET_CLEAR(); code = pthread_create(&dbWatcherPid, &tattr, dbWatcher, (void *)2); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(dbWatcher, 20480, LWP_NORMAL_PRIORITY, (void *)2, "dbWatcher", &dbWatcherPid); #endif if (code) { TapeLog(0, 0, code, 0, "Can't create database monitor task"); exit(1); } TLog(0, "Starting Tape Coordinator: Port offset %u Debug level %u\n", portOffset, debugLevel); TLog(0, "Token expires: %s\n", cTIME(&tokenExpires)); rx_StartServer(1); /* Donate this process to the server process pool */ TLog(0, "Error: StartServer returned"); exit(1); }