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_prototypes.h"
38 /* code to manage dump schedules
39 * specific to the ubik database implementation
42 extern struct bc_config *bc_globalConfig;
43 extern struct udbHandleS udbHandle;
46 static int ListDumpSchedule(struct bc_dumpSchedule *adump, int alevel);
48 /* ------------------------------------
49 * command level routines
50 * ------------------------------------
56 * parm 0: list of dump names
57 * parm 1: expiration date (list)
61 bc_AddDumpCmd(struct cmd_syndesc *as, void *arock)
63 register char *dname; /* dump schedule name */
65 afs_int32 expType, expDate;
66 register struct cmd_item *ti;
69 /* if an expiration date has been specified */
70 if (as->parms[1].items) {
71 code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
73 printf("Invalid expiration date syntax\n");
77 /* no expiration date specified */
79 expType = BC_NO_EXPDATE;
82 /* lock schedules and check validity */
83 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
85 code = bc_LockText(ctPtr);
89 code = bc_UpdateDumpSchedule();
91 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
95 /* process each dump name using the expiration date computed above */
96 for (ti = as->parms[0].items; ti != 0; ti = ti->next) {
97 /* get next dump name to process */
100 /* validate the name dump name length */
101 if (strlen(dname) >= BU_MAX_DUMP_PATH) {
102 afs_com_err(whoami, 0, "Dump names must be < %d characters",
104 afs_com_err(whoami, 0, "Dump %s not added", dname);
110 bc_CreateDumpSchedule(bc_globalConfig, dname, expDate, expType);
113 afs_com_err(whoami, 0, "Dump already exists");
115 afs_com_err(whoami, 0, "Invalid path name '%s'", dname);
117 afs_com_err(whoami, 0, "Name specification error");
119 afs_com_err(whoami, code, "; Failed to create dump schedule");
123 /* save the new schedule item */
124 code = bc_SaveDumpSchedule();
126 afs_com_err(whoami, code, "Cannot save dump schedule");
127 afs_com_err(whoami, 0,
128 "Changes are temporary - for this session only");
132 afs_com_err(whoami, 0, "Created new dump schedule %s", dname);
136 if (ctPtr->lockHandle)
137 bc_UnlockText(ctPtr);
143 * delete a dump schedule
147 bc_DeleteDumpCmd(struct cmd_syndesc *as, void *arock)
149 /* parm 0 is vol set name
150 * parm 1 is dump schedule name
152 register char *dname;
154 udbClientTextP ctPtr;
156 /* lock schedules and check validity */
157 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
159 code = bc_LockText(ctPtr);
163 code = bc_UpdateDumpSchedule();
165 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
169 dname = as->parms[0].items->data;
171 code = bc_DeleteDumpSchedule(bc_globalConfig, dname);
174 afs_com_err(whoami, 0, "No such dump as %s", dname);
176 afs_com_err(whoami, code, "; Failed to delete dump schedule");
180 code = bc_SaveDumpSchedule();
182 printf("backup: deleted dump schedule %s\n", dname);
184 afs_com_err(whoami, code, "Cannot save dump schedule file");
185 afs_com_err(whoami, 0, "Deletion is temporary - for this session only");
189 if (ctPtr->lockHandle != 0)
190 bc_UnlockText(ctPtr);
195 * Print out the dump schedule tree whose root is adump. Alevel should
196 * be passed in as 0, and is incremented for the recursive calls
198 * adump - ptr to the root node of a dump schedule
203 ListDumpSchedule(register struct bc_dumpSchedule *adump, int alevel)
206 register struct bc_dumpSchedule *child;
208 /* sanity check for loops */
210 printf("backup: recursing listing dump schedule\n");
214 /* move to appropriate indentation level */
215 for (i = 0; i < alevel; i++)
218 /* name is a pathname style name, determine trailing name and only print
222 printf("/%s ", tailCompPtr(adump->name));
225 /* list expiration time */
226 switch (adump->expType) {
228 /* absolute expiration date. Never expires if date is 0 */
229 if (adump->expDate) {
230 time_t t = adump->expDate;
231 printf("expires at %.24s", cTIME(&t));
237 struct ktime_date kt;
239 /* expiration date relative to the time that the dump is done */
240 LongTo_ktimeRelDate(adump->expDate, &kt);
241 printf(" expires in %s", RelDatetoString(&kt));
249 for (child = adump->firstChild; child; child = child->nextSibling)
250 ListDumpSchedule(child, alevel + 1);
255 /* bc_ListDumpScheduleCmd
256 * list the (internally held) dump schedule tree
262 bc_ListDumpScheduleCmd(struct cmd_syndesc *as, void *arock)
266 register struct bc_dumpSchedule *tdump;
268 /* first check to see if schedules must be updated */
269 code = bc_UpdateDumpSchedule();
271 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
275 /* go through entire list, displaying trees for root-level dump
278 for (tdump = bc_globalConfig->dsched; tdump; tdump = tdump->next) {
279 /* if this is a root-level dump, show it and its kids */
281 ListDumpSchedule(tdump, 0);
288 * Set/clear expiration date on existing dump node
290 * parm 0: list of dump names
291 * parm 1: expiration date (list)
295 bc_SetExpCmd(struct cmd_syndesc *as, void *arock)
297 register char *dname; /* dump schedule name */
298 register struct cmd_item *ti;
299 struct bc_dumpSchedule *node, *parent;
300 afs_int32 expType, expDate;
301 udbClientTextP ctPtr;
304 /* if an expiration date has been specified */
305 if (as->parms[1].items) {
306 code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
308 printf("Invalid expiration date syntax\n");
312 /* no expiration date specified */
314 expType = BC_NO_EXPDATE;
317 /* lock schedules and check validity */
318 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
320 code = bc_LockText(ctPtr);
324 code = bc_UpdateDumpSchedule();
326 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
330 /* process each dump name using the expiration date computed above */
331 for (ti = as->parms[0].items; ti != 0; ti = ti->next) {
332 /* get next dump name to process */
335 /* validate the name dump name length */
336 if (strlen(dname) >= BU_MAX_DUMP_PATH) {
338 afs_com_err(whoami, 0, "Dump names must be < %d characters",
340 afs_com_err(whoami, 0, "Dump %s not added", dname);
344 code = FindDump(bc_globalConfig, dname, &parent, &node);
346 afs_com_err(whoami, 0, "Dump level %s not found", dname);
350 node->expDate = expDate;
351 node->expType = expType;
354 code = bc_SaveDumpSchedule();
356 afs_com_err(whoami, code, "Cannot save dump schedule");
357 afs_com_err(whoami, 0,
358 "Expiration changes effective for this session only");
362 if (ctPtr->lockHandle)
363 bc_UnlockText(ctPtr);
369 /* ------------------------------------
370 * general dump schedule handling routines
371 * ------------------------------------
375 bc_ParseDumpSchedule(void)
378 char dsname[256], period[64];
381 udbClientTextP ctPtr;
382 register struct bc_dumpSchedule *tds;
383 struct bc_dumpSchedule **ppds, *pds;
384 afs_int32 expDate, expType;
386 register FILE *stream;
388 /* initialize locally used variables */
389 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
390 stream = ctPtr->textStream;
392 if (ctPtr->textSize == 0) /* nothing defined yet */
396 return (BC_INTERNALERROR);
400 /* check the magic number and version */
401 tp = fgets(tbuffer, sizeof(tbuffer), stream);
403 /* can't read first line - error */
404 return (BC_INTERNALERROR);
406 afs_int32 dsmagic, dsversion;
408 /* read the first line, and then check magic # and version */
410 code = sscanf(tbuffer, "%d %d", &dsmagic, &dsversion);
412 || (dsmagic != BC_SCHEDULE_MAGIC)
413 || (dsversion != BC_SCHEDULE_VERSION)
415 /* invalid or unexpected header - error */
416 afs_com_err(whoami, 0, "Unable to understand dump schedule file");
417 return (BC_INTERNALERROR);
422 /* read all of the lines out */
423 tp = fgets(tbuffer, sizeof(tbuffer), stream);
425 break; /* hit eof? */
427 sscanf(tbuffer, "%s %s %d %d", dsname, period, &expDate,
430 afs_com_err(whoami, 0,
431 "Syntax error in dump schedule file, line is: %s",
433 return (BC_INTERNALERROR);
436 (struct bc_dumpSchedule *)malloc(sizeof(struct bc_dumpSchedule));
437 memset(tds, 0, sizeof(*tds));
439 tds->next = (struct bc_dumpSchedule *)0;
440 tds->name = (char *)malloc(strlen(dsname) + 1);
441 strcpy(tds->name, dsname);
443 tds->expDate = expDate;
444 tds->expType = expType;
446 /* find the end of the schedule list, and append the new item to it */
447 ppds = &bc_globalConfig->dsched;
459 bc_SaveDumpSchedule(void)
461 struct bc_dumpSchedule *tdump;
462 udbClientTextP ctPtr;
465 extern struct bc_config *bc_globalConfig;
467 /* setup the right ptr */
468 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
471 if (ctPtr->lockHandle == 0)
472 return (BC_INTERNALERROR);
474 /* truncate the file */
475 code = ftruncate(fileno(ctPtr->textStream), 0);
479 rewind(ctPtr->textStream);
481 /* write the new information */
482 fprintf(ctPtr->textStream, "%d %d\n", BC_SCHEDULE_MAGIC,
483 BC_SCHEDULE_VERSION);
485 for (tdump = bc_globalConfig->dsched; tdump; tdump = tdump->next) {
486 fprintf(ctPtr->textStream, "%s %s %d %d\n", tdump->name, "any",
487 tdump->expDate, tdump->expType);
490 if (ferror(ctPtr->textStream))
491 return (BC_INTERNALERROR);
493 fflush(ctPtr->textStream); /* debug */
496 code = bcdb_SaveTextFile(ctPtr);
500 /* increment local version number */
501 ctPtr->textVersion++;
503 /* update locally stored file size */
504 ctPtr->textSize = filesize(ctPtr->textStream);
510 /* ------------------------------------
511 * misc. support routines - specific to dump schedules
512 * ------------------------------------
516 bc_UpdateDumpSchedule(void)
518 struct bc_dumpSchedule *dumpPtr, *nextDumpPtr;
519 struct udbHandleS *uhptr = &udbHandle;
520 udbClientTextP ctPtr;
524 /* lock schedules and check validity */
525 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
527 code = bc_CheckTextVersion(ctPtr);
528 if (code != BC_VERSIONMISMATCH) {
529 ERROR(code); /* Version matches or some other error */
532 /* Must update the dump schedules */
533 /* If we are not already locked, then lock it now */
534 if (!ctPtr->lockHandle) {
535 code = bc_LockText(ctPtr);
541 if (ctPtr->textVersion != -1) {
542 printf("backup: obsolete dump schedule - updating\n");
544 /* clear all old schedule information */
545 dumpPtr = bc_globalConfig->dsched;
547 nextDumpPtr = dumpPtr->next;
549 dumpPtr = nextDumpPtr;
551 bc_globalConfig->dsched = 0;;
554 /* open a temp file to store the config text received from buserver *
555 * The open file stream is stored in ctPtr->textStream */
557 bc_openTextFile(ctPtr,
559 tmpTextFileNames[TB_DUMPSCHEDULE][0]);
562 /* now get a fresh set of information from the database */
563 code = bcdb_GetTextFile(ctPtr);
567 /* fetch the version number */
569 ubik_BUDB_GetTextVersion(uhptr->uh_client, 0, ctPtr->textType,
570 &ctPtr->textVersion);
575 code = bc_ParseDumpSchedule();
579 /* rebuild the tree */
580 code = bc_ProcessDumpSchedule(bc_globalConfig);
585 if (lock && ctPtr->lockHandle)
586 bc_UnlockText(ctPtr);