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>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
31 #include <afs/ktime.h>
32 #include <afs/budb_client.h>
34 #include <afs/com_err.h>
35 #include <afs/bubasics.h>
37 #include "error_macros.h"
39 /* code to manage dump schedules
40 * specific to the ubik database implementation
43 afs_int32 bc_UpdateDumpSchedule();
44 extern struct bc_config *bc_globalConfig;
45 extern struct udbHandleS udbHandle;
48 static ListDumpSchedule();
50 /* ------------------------------------
51 * command level routines
52 * ------------------------------------
58 * parm 0: list of dump names
59 * parm 1: expiration date (list)
63 bc_AddDumpCmd(struct cmd_syndesc *as, void *arock)
65 register char *dname; /* dump schedule name */
67 afs_int32 expType, expDate;
68 register struct cmd_item *ti;
71 afs_int32 bc_ParseExpiration();
73 /* if an expiration date has been specified */
74 if (as->parms[1].items) {
75 code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
77 printf("Invalid expiration date syntax\n");
81 /* no expiration date specified */
83 expType = BC_NO_EXPDATE;
86 /* lock schedules and check validity */
87 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
89 code = bc_LockText(ctPtr);
93 code = bc_UpdateDumpSchedule();
95 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
99 /* process each dump name using the expiration date computed above */
100 for (ti = as->parms[0].items; ti != 0; ti = ti->next) {
101 /* get next dump name to process */
104 /* validate the name dump name length */
105 if (strlen(dname) >= BU_MAX_DUMP_PATH) {
106 afs_com_err(whoami, 0, "Dump names must be < %d characters",
108 afs_com_err(whoami, 0, "Dump %s not added", dname);
114 bc_CreateDumpSchedule(bc_globalConfig, dname, expDate, expType);
117 afs_com_err(whoami, 0, "Dump already exists");
119 afs_com_err(whoami, 0, "Invalid path name '%s'", dname);
121 afs_com_err(whoami, 0, "Name specification error");
123 afs_com_err(whoami, code, "; Failed to create dump schedule");
127 /* save the new schedule item */
128 code = bc_SaveDumpSchedule();
130 afs_com_err(whoami, code, "Cannot save dump schedule");
131 afs_com_err(whoami, 0,
132 "Changes are temporary - for this session only");
136 afs_com_err(whoami, 0, "Created new dump schedule %s", dname);
140 if (ctPtr->lockHandle)
141 bc_UnlockText(ctPtr);
147 * delete a dump schedule
151 bc_DeleteDumpCmd(struct cmd_syndesc *as, void *arock)
153 /* parm 0 is vol set name
154 * parm 1 is dump schedule name
156 register char *dname;
158 udbClientTextP ctPtr;
160 /* lock schedules and check validity */
161 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
163 code = bc_LockText(ctPtr);
167 code = bc_UpdateDumpSchedule();
169 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
173 dname = as->parms[0].items->data;
175 code = bc_DeleteDumpSchedule(bc_globalConfig, dname);
178 afs_com_err(whoami, 0, "No such dump as %s", dname);
180 afs_com_err(whoami, code, "; Failed to delete dump schedule");
184 code = bc_SaveDumpSchedule();
186 printf("backup: deleted dump schedule %s\n", dname);
188 afs_com_err(whoami, code, "Cannot save dump schedule file");
189 afs_com_err(whoami, 0, "Deletion is temporary - for this session only");
193 if (ctPtr->lockHandle != 0)
194 bc_UnlockText(ctPtr);
199 * Print out the dump schedule tree whose root is adump. Alevel should
200 * be passed in as 0, and is incremented for the recursive calls
202 * adump - ptr to the root node of a dump schedule
207 ListDumpSchedule(register struct bc_dumpSchedule *adump, int alevel)
210 register struct bc_dumpSchedule *child;
214 /* sanity check for loops */
216 printf("backup: recursing listing dump schedule\n");
220 /* move to appropriate indentation level */
221 for (i = 0; i < alevel; i++)
224 /* name is a pathname style name, determine trailing name and only print
228 printf("/%s ", tailCompPtr(adump->name));
231 /* list expiration time */
232 switch (adump->expType) {
234 /* absolute expiration date. Never expires if date is 0 */
235 if (adump->expDate) {
236 time_t t = adump->expDate;
237 printf("expires at %.24s", cTIME(&t));
243 struct ktime_date kt;
245 /* expiration date relative to the time that the dump is done */
246 LongTo_ktimeRelDate(adump->expDate, &kt);
247 printf(" expires in %s", RelDatetoString(&kt));
255 for (child = adump->firstChild; child; child = child->nextSibling)
256 ListDumpSchedule(child, alevel + 1);
261 /* bc_ListDumpScheduleCmd
262 * list the (internally held) dump schedule tree
268 bc_ListDumpScheduleCmd(struct cmd_syndesc *as, void *arock)
272 register struct bc_dumpSchedule *tdump;
274 /* first check to see if schedules must be updated */
275 code = bc_UpdateDumpSchedule();
277 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
281 /* go through entire list, displaying trees for root-level dump
284 for (tdump = bc_globalConfig->dsched; tdump; tdump = tdump->next) {
285 /* if this is a root-level dump, show it and its kids */
287 ListDumpSchedule(tdump, 0);
294 * Set/clear expiration date on existing dump node
296 * parm 0: list of dump names
297 * parm 1: expiration date (list)
301 bc_SetExpCmd(struct cmd_syndesc *as, void *arock)
303 register char *dname; /* dump schedule name */
304 register struct cmd_item *ti;
305 struct bc_dumpSchedule *node, *parent;
306 afs_int32 expType, expDate;
307 udbClientTextP ctPtr;
310 afs_int32 bc_ParseExpiration();
312 /* if an expiration date has been specified */
313 if (as->parms[1].items) {
314 code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
316 printf("Invalid expiration date syntax\n");
320 /* no expiration date specified */
322 expType = BC_NO_EXPDATE;
325 /* lock schedules and check validity */
326 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
328 code = bc_LockText(ctPtr);
332 code = bc_UpdateDumpSchedule();
334 afs_com_err(whoami, code, "; Can't retrieve dump schedule");
338 /* process each dump name using the expiration date computed above */
339 for (ti = as->parms[0].items; ti != 0; ti = ti->next) {
340 /* get next dump name to process */
343 /* validate the name dump name length */
344 if (strlen(dname) >= BU_MAX_DUMP_PATH) {
346 afs_com_err(whoami, 0, "Dump names must be < %d characters",
348 afs_com_err(whoami, 0, "Dump %s not added", dname);
352 code = FindDump(bc_globalConfig, dname, &parent, &node);
354 afs_com_err(whoami, 0, "Dump level %s not found", dname);
358 node->expDate = expDate;
359 node->expType = expType;
362 code = bc_SaveDumpSchedule();
364 afs_com_err(whoami, code, "Cannot save dump schedule");
365 afs_com_err(whoami, 0,
366 "Expiration changes effective for this session only");
370 if (ctPtr->lockHandle)
371 bc_UnlockText(ctPtr);
377 /* ------------------------------------
378 * general dump schedule handling routines
379 * ------------------------------------
382 bc_ParseDumpSchedule()
385 char dsname[256], period[64];
388 udbClientTextP ctPtr;
389 register struct bc_dumpSchedule *tds;
390 struct bc_dumpSchedule **ppds, *pds;
391 afs_int32 expDate, expType;
393 register FILE *stream;
395 /* initialize locally used variables */
396 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
397 stream = ctPtr->textStream;
399 if (ctPtr->textSize == 0) /* nothing defined yet */
403 return (BC_INTERNALERROR);
407 /* check the magic number and version */
408 tp = fgets(tbuffer, sizeof(tbuffer), stream);
410 /* can't read first line - error */
411 return (BC_INTERNALERROR);
413 afs_int32 dsmagic, dsversion;
415 /* read the first line, and then check magic # and version */
417 code = sscanf(tbuffer, "%d %d", &dsmagic, &dsversion);
419 || (dsmagic != BC_SCHEDULE_MAGIC)
420 || (dsversion != BC_SCHEDULE_VERSION)
422 /* invalid or unexpected header - error */
423 afs_com_err(whoami, 0, "Unable to understand dump schedule file");
424 return (BC_INTERNALERROR);
429 /* read all of the lines out */
430 tp = fgets(tbuffer, sizeof(tbuffer), stream);
432 break; /* hit eof? */
434 sscanf(tbuffer, "%s %s %d %d", dsname, period, &expDate,
437 afs_com_err(whoami, 0,
438 "Syntax error in dump schedule file, line is: %s",
440 return (BC_INTERNALERROR);
443 (struct bc_dumpSchedule *)malloc(sizeof(struct bc_dumpSchedule));
444 memset(tds, 0, sizeof(*tds));
446 tds->next = (struct bc_dumpSchedule *)0;
447 tds->name = (char *)malloc(strlen(dsname) + 1);
448 strcpy(tds->name, dsname);
450 tds->expDate = expDate;
451 tds->expType = expType;
453 /* find the end of the schedule list, and append the new item to it */
454 ppds = &bc_globalConfig->dsched;
466 bc_SaveDumpSchedule()
468 struct bc_dumpSchedule *tdump;
469 udbClientTextP ctPtr;
472 extern struct bc_config *bc_globalConfig;
473 extern afs_int32 filesize();
475 /* setup the right ptr */
476 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
479 if (ctPtr->lockHandle == 0)
480 return (BC_INTERNALERROR);
482 /* truncate the file */
483 code = ftruncate(fileno(ctPtr->textStream), 0);
487 rewind(ctPtr->textStream);
489 /* write the new information */
490 fprintf(ctPtr->textStream, "%d %d\n", BC_SCHEDULE_MAGIC,
491 BC_SCHEDULE_VERSION);
493 for (tdump = bc_globalConfig->dsched; tdump; tdump = tdump->next) {
494 fprintf(ctPtr->textStream, "%s %s %d %d\n", tdump->name, "any",
495 tdump->expDate, tdump->expType);
498 if (ferror(ctPtr->textStream))
499 return (BC_INTERNALERROR);
501 fflush(ctPtr->textStream); /* debug */
504 code = bcdb_SaveTextFile(ctPtr);
508 /* increment local version number */
509 ctPtr->textVersion++;
511 /* update locally stored file size */
512 ctPtr->textSize = filesize(ctPtr->textStream);
518 /* ------------------------------------
519 * misc. support routines - specific to dump schedules
520 * ------------------------------------
524 bc_UpdateDumpSchedule()
526 struct bc_dumpSchedule *dumpPtr, *nextDumpPtr;
527 struct udbHandleS *uhptr = &udbHandle;
528 udbClientTextP ctPtr;
532 /* lock schedules and check validity */
533 ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
535 code = bc_CheckTextVersion(ctPtr);
536 if (code != BC_VERSIONMISMATCH) {
537 ERROR(code); /* Version matches or some other error */
540 /* Must update the dump schedules */
541 /* If we are not already locked, then lock it now */
542 if (!ctPtr->lockHandle) {
543 code = bc_LockText(ctPtr);
549 if (ctPtr->textVersion != -1) {
550 printf("backup: obsolete dump schedule - updating\n");
552 /* clear all old schedule information */
553 dumpPtr = bc_globalConfig->dsched;
555 nextDumpPtr = dumpPtr->next;
557 dumpPtr = nextDumpPtr;
559 bc_globalConfig->dsched = 0;;
562 /* open a temp file to store the config text received from buserver *
563 * The open file stream is stored in ctPtr->textStream */
565 bc_openTextFile(ctPtr,
567 tmpTextFileNames[TB_DUMPSCHEDULE][0]);
570 /* now get a fresh set of information from the database */
571 code = bcdb_GetTextFile(ctPtr);
575 /* fetch the version number */
577 ubik_BUDB_GetTextVersion(uhptr->uh_client, 0, ctPtr->textType,
578 &ctPtr->textVersion);
583 code = bc_ParseDumpSchedule();
587 /* rebuild the tree */
588 code = bc_ProcessDumpSchedule(bc_globalConfig);
593 if (lock && ctPtr->lockHandle)
594 bc_UnlockText(ctPtr);