2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
14 #include <sys/types.h>
17 #include <afsconfig.h>
18 #include <afs/param.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
29 #include <afs/ktime.h>
30 #include <afs/budb_client.h>
32 #include <afs/com_err.h>
33 #include <afs/bubasics.h>
35 #include "error_macros.h"
36 #include "bucoord_internal.h"
37 #include "bucoord_prototypes.h"
39 /* code to manage dump schedules
40 * specific to the ubik database implementation
43 extern struct bc_config *bc_globalConfig;
44 extern struct udbHandleS udbHandle;
47 static int ListDumpSchedule(struct bc_dumpSchedule *adump, int alevel);
49 /* ------------------------------------
50 * command level routines
51 * ------------------------------------
57 * parm 0: list of dump names
58 * parm 1: expiration date (list)
62 bc_AddDumpCmd(struct cmd_syndesc *as, void *arock)
64 char *dname; /* dump schedule name */
66 afs_int32 expType, expDate;
70 /* if an expiration date has been specified */
71 if (as->parms[1].items) {
72 code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
74 printf("Invalid expiration date syntax\n");
78 /* no expiration date specified */
80 expType = BC_NO_EXPDATE;
83 /* lock schedules and check validity */
84 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
86 code = bc_LockText(ctPtr);
90 code = bc_UpdateDumpSchedule();
92 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
96 /* process each dump name using the expiration date computed above */
97 for (ti = as->parms[0].items; ti != 0; ti = ti->next) {
98 /* get next dump name to process */
101 /* validate the name dump name length */
102 if (strlen(dname) >= BU_MAX_DUMP_PATH) {
103 afs_com_err(whoami, 0, "Dump names must be < %d characters",
105 afs_com_err(whoami, 0, "Dump %s not added", dname);
111 bc_CreateDumpSchedule(bc_globalConfig, dname, expDate, expType);
114 afs_com_err(whoami, 0, "Dump already exists");
116 afs_com_err(whoami, 0, "Invalid path name '%s'", dname);
118 afs_com_err(whoami, 0, "Name specification error");
120 afs_com_err(whoami, code, "; Failed to create dump schedule");
124 /* save the new schedule item */
125 code = bc_SaveDumpSchedule();
127 afs_com_err(whoami, code, "Cannot save dump schedule");
128 afs_com_err(whoami, 0,
129 "Changes are temporary - for this session only");
133 afs_com_err(whoami, 0, "Created new dump schedule %s", dname);
137 if (ctPtr->lockHandle)
138 bc_UnlockText(ctPtr);
144 * delete a dump schedule
148 bc_DeleteDumpCmd(struct cmd_syndesc *as, void *arock)
150 /* parm 0 is vol set name
151 * parm 1 is dump schedule name
155 udbClientTextP ctPtr;
157 /* lock schedules and check validity */
158 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
160 code = bc_LockText(ctPtr);
164 code = bc_UpdateDumpSchedule();
166 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
170 dname = as->parms[0].items->data;
172 code = bc_DeleteDumpSchedule(bc_globalConfig, dname);
175 afs_com_err(whoami, 0, "No such dump as %s", dname);
177 afs_com_err(whoami, code, "; Failed to delete dump schedule");
181 code = bc_SaveDumpSchedule();
183 printf("backup: deleted dump schedule %s\n", dname);
185 afs_com_err(whoami, code, "Cannot save dump schedule file");
186 afs_com_err(whoami, 0, "Deletion is temporary - for this session only");
190 if (ctPtr->lockHandle != 0)
191 bc_UnlockText(ctPtr);
196 * Print out the dump schedule tree whose root is adump. Alevel should
197 * be passed in as 0, and is incremented for the recursive calls
199 * adump - ptr to the root node of a dump schedule
204 ListDumpSchedule(struct bc_dumpSchedule *adump, int alevel)
207 struct bc_dumpSchedule *child;
209 /* sanity check for loops */
211 printf("backup: recursing listing dump schedule\n");
215 /* move to appropriate indentation level */
216 for (i = 0; i < alevel; i++)
219 /* name is a pathname style name, determine trailing name and only print
223 printf("/%s ", tailCompPtr(adump->name));
226 /* list expiration time */
227 switch (adump->expType) {
229 /* absolute expiration date. Never expires if date is 0 */
230 if (adump->expDate) {
231 time_t t = adump->expDate;
232 printf("expires at %.24s", cTIME(&t));
238 struct ktime_date kt;
240 /* expiration date relative to the time that the dump is done */
241 LongTo_ktimeRelDate(adump->expDate, &kt);
242 printf(" expires in %s", RelDatetoString(&kt));
250 for (child = adump->firstChild; child; child = child->nextSibling)
251 ListDumpSchedule(child, alevel + 1);
256 /* bc_ListDumpScheduleCmd
257 * list the (internally held) dump schedule tree
263 bc_ListDumpScheduleCmd(struct cmd_syndesc *as, void *arock)
267 struct bc_dumpSchedule *tdump;
269 /* first check to see if schedules must be updated */
270 code = bc_UpdateDumpSchedule();
272 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
276 /* go through entire list, displaying trees for root-level dump
279 for (tdump = bc_globalConfig->dsched; tdump; tdump = tdump->next) {
280 /* if this is a root-level dump, show it and its kids */
282 ListDumpSchedule(tdump, 0);
289 * Set/clear expiration date on existing dump node
291 * parm 0: list of dump names
292 * parm 1: expiration date (list)
296 bc_SetExpCmd(struct cmd_syndesc *as, void *arock)
298 char *dname; /* dump schedule name */
300 struct bc_dumpSchedule *node, *parent;
301 afs_int32 expType, expDate;
302 udbClientTextP ctPtr;
305 /* if an expiration date has been specified */
306 if (as->parms[1].items) {
307 code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
309 printf("Invalid expiration date syntax\n");
313 /* no expiration date specified */
315 expType = BC_NO_EXPDATE;
318 /* lock schedules and check validity */
319 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
321 code = bc_LockText(ctPtr);
325 code = bc_UpdateDumpSchedule();
327 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
331 /* process each dump name using the expiration date computed above */
332 for (ti = as->parms[0].items; ti != 0; ti = ti->next) {
333 /* get next dump name to process */
336 /* validate the name dump name length */
337 if (strlen(dname) >= BU_MAX_DUMP_PATH) {
339 afs_com_err(whoami, 0, "Dump names must be < %d characters",
341 afs_com_err(whoami, 0, "Dump %s not added", dname);
345 code = FindDump(bc_globalConfig, dname, &parent, &node);
347 afs_com_err(whoami, 0, "Dump level %s not found", dname);
351 node->expDate = expDate;
352 node->expType = expType;
355 code = bc_SaveDumpSchedule();
357 afs_com_err(whoami, code, "Cannot save dump schedule");
358 afs_com_err(whoami, 0,
359 "Expiration changes effective for this session only");
363 if (ctPtr->lockHandle)
364 bc_UnlockText(ctPtr);
370 /* ------------------------------------
371 * general dump schedule handling routines
372 * ------------------------------------
376 bc_ParseDumpSchedule(void)
379 char dsname[256], period[64];
382 udbClientTextP ctPtr;
383 struct bc_dumpSchedule *tds;
384 struct bc_dumpSchedule **ppds, *pds;
385 afs_int32 expDate, expType;
389 /* initialize locally used variables */
390 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
391 stream = ctPtr->textStream;
393 if (ctPtr->textSize == 0) /* nothing defined yet */
397 return (BC_INTERNALERROR);
401 /* check the magic number and version */
402 tp = fgets(tbuffer, sizeof(tbuffer), stream);
404 /* can't read first line - error */
405 return (BC_INTERNALERROR);
407 afs_int32 dsmagic, dsversion;
409 /* read the first line, and then check magic # and version */
411 code = sscanf(tbuffer, "%d %d", &dsmagic, &dsversion);
413 || (dsmagic != BC_SCHEDULE_MAGIC)
414 || (dsversion != BC_SCHEDULE_VERSION)
416 /* invalid or unexpected header - error */
417 afs_com_err(whoami, 0, "Unable to understand dump schedule file");
418 return (BC_INTERNALERROR);
423 /* read all of the lines out */
424 tp = fgets(tbuffer, sizeof(tbuffer), stream);
426 break; /* hit eof? */
428 sscanf(tbuffer, "%s %s %d %d", dsname, period, &expDate,
431 afs_com_err(whoami, 0,
432 "Syntax error in dump schedule file, line is: %s",
434 return (BC_INTERNALERROR);
437 (struct bc_dumpSchedule *)malloc(sizeof(struct bc_dumpSchedule));
438 memset(tds, 0, sizeof(*tds));
440 tds->next = (struct bc_dumpSchedule *)0;
441 tds->name = (char *)malloc(strlen(dsname) + 1);
442 strcpy(tds->name, dsname);
444 tds->expDate = expDate;
445 tds->expType = expType;
447 /* find the end of the schedule list, and append the new item to it */
448 ppds = &bc_globalConfig->dsched;
460 bc_SaveDumpSchedule(void)
462 struct bc_dumpSchedule *tdump;
463 udbClientTextP ctPtr;
466 extern struct bc_config *bc_globalConfig;
468 /* setup the right ptr */
469 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
472 if (ctPtr->lockHandle == 0)
473 return (BC_INTERNALERROR);
475 /* truncate the file */
476 code = ftruncate(fileno(ctPtr->textStream), 0);
480 rewind(ctPtr->textStream);
482 /* write the new information */
483 fprintf(ctPtr->textStream, "%d %d\n", BC_SCHEDULE_MAGIC,
484 BC_SCHEDULE_VERSION);
486 for (tdump = bc_globalConfig->dsched; tdump; tdump = tdump->next) {
487 fprintf(ctPtr->textStream, "%s %s %d %d\n", tdump->name, "any",
488 tdump->expDate, tdump->expType);
491 if (ferror(ctPtr->textStream))
492 return (BC_INTERNALERROR);
494 fflush(ctPtr->textStream); /* debug */
497 code = bcdb_SaveTextFile(ctPtr);
501 /* increment local version number */
502 ctPtr->textVersion++;
504 /* update locally stored file size */
505 ctPtr->textSize = filesize(ctPtr->textStream);
511 /* ------------------------------------
512 * misc. support routines - specific to dump schedules
513 * ------------------------------------
517 bc_UpdateDumpSchedule(void)
519 struct bc_dumpSchedule *dumpPtr, *nextDumpPtr;
520 struct udbHandleS *uhptr = &udbHandle;
521 udbClientTextP ctPtr;
525 /* lock schedules and check validity */
526 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
528 code = bc_CheckTextVersion(ctPtr);
529 if (code != BC_VERSIONMISMATCH) {
530 ERROR(code); /* Version matches or some other error */
533 /* Must update the dump schedules */
534 /* If we are not already locked, then lock it now */
535 if (!ctPtr->lockHandle) {
536 code = bc_LockText(ctPtr);
542 if (ctPtr->textVersion != -1) {
543 printf("backup: obsolete dump schedule - updating\n");
545 /* clear all old schedule information */
546 dumpPtr = bc_globalConfig->dsched;
548 nextDumpPtr = dumpPtr->next;
550 dumpPtr = nextDumpPtr;
552 bc_globalConfig->dsched = 0;;
555 /* open a temp file to store the config text received from buserver *
556 * The open file stream is stored in ctPtr->textStream */
558 bc_openTextFile(ctPtr,
560 tmpTextFileNames[TB_DUMPSCHEDULE][0]);
563 /* now get a fresh set of information from the database */
564 code = bcdb_GetTextFile(ctPtr);
568 /* fetch the version number */
570 ubik_BUDB_GetTextVersion(uhptr->uh_client, 0, ctPtr->textType,
571 &ctPtr->textVersion);
576 code = bc_ParseDumpSchedule();
580 /* rebuild the tree */
581 code = bc_ProcessDumpSchedule(bc_globalConfig);
586 if (lock && ctPtr->lockHandle)
587 bc_UnlockText(ctPtr);