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 <afsconfig.h>
15 #include <afs/param.h>
19 #include <afs/ktime.h>
20 #include <afs/budb_client.h>
22 #include <afs/com_err.h>
23 #include <afs/bubasics.h>
26 #include "error_macros.h"
27 #include "bucoord_internal.h"
28 #include "bucoord_prototypes.h"
30 /* code to manage dump schedules
31 * specific to the ubik database implementation
34 extern struct bc_config
*bc_globalConfig
;
35 extern struct udbHandleS udbHandle
;
38 static int ListDumpSchedule(struct bc_dumpSchedule
*adump
, int alevel
);
40 /* ------------------------------------
41 * command level routines
42 * ------------------------------------
48 * parm 0: list of dump names
49 * parm 1: expiration date (list)
53 bc_AddDumpCmd(struct cmd_syndesc
*as
, void *arock
)
55 char *dname
; /* dump schedule name */
57 afs_int32 expType
, expDate
;
61 /* if an expiration date has been specified */
62 if (as
->parms
[1].items
) {
63 code
= bc_ParseExpiration(&as
->parms
[1], &expType
, &expDate
);
65 printf("Invalid expiration date syntax\n");
69 /* no expiration date specified */
71 expType
= BC_NO_EXPDATE
;
74 /* lock schedules and check validity */
75 ctPtr
= &bc_globalConfig
->configText
[TB_DUMPSCHEDULE
];
77 code
= bc_LockText(ctPtr
);
81 code
= bc_UpdateDumpSchedule();
83 afs_com_err(whoami
, code
, "; Can't retrieve dump schedule");
87 /* process each dump name using the expiration date computed above */
88 for (ti
= as
->parms
[0].items
; ti
!= 0; ti
= ti
->next
) {
89 /* get next dump name to process */
92 /* validate the name dump name length */
93 if (strlen(dname
) >= BU_MAX_DUMP_PATH
) {
94 afs_com_err(whoami
, 0, "Dump names must be < %d characters",
96 afs_com_err(whoami
, 0, "Dump %s not added", dname
);
102 bc_CreateDumpSchedule(bc_globalConfig
, dname
, expDate
, expType
);
105 afs_com_err(whoami
, 0, "Dump already exists");
107 afs_com_err(whoami
, 0, "Invalid path name '%s'", dname
);
109 afs_com_err(whoami
, 0, "Name specification error");
111 afs_com_err(whoami
, code
, "; Failed to create dump schedule");
115 /* save the new schedule item */
116 code
= bc_SaveDumpSchedule();
118 afs_com_err(whoami
, code
, "Cannot save dump schedule");
119 afs_com_err(whoami
, 0,
120 "Changes are temporary - for this session only");
124 afs_com_err(whoami
, 0, "Created new dump schedule %s", dname
);
128 if (ctPtr
->lockHandle
)
129 bc_UnlockText(ctPtr
);
135 * delete a dump schedule
139 bc_DeleteDumpCmd(struct cmd_syndesc
*as
, void *arock
)
141 /* parm 0 is vol set name
142 * parm 1 is dump schedule name
146 udbClientTextP ctPtr
;
148 /* lock schedules and check validity */
149 ctPtr
= &bc_globalConfig
->configText
[TB_DUMPSCHEDULE
];
151 code
= bc_LockText(ctPtr
);
155 code
= bc_UpdateDumpSchedule();
157 afs_com_err(whoami
, code
, "; Can't retrieve dump schedule");
161 dname
= as
->parms
[0].items
->data
;
163 code
= bc_DeleteDumpSchedule(bc_globalConfig
, dname
);
166 afs_com_err(whoami
, 0, "No such dump as %s", dname
);
168 afs_com_err(whoami
, code
, "; Failed to delete dump schedule");
172 code
= bc_SaveDumpSchedule();
174 printf("backup: deleted dump schedule %s\n", dname
);
176 afs_com_err(whoami
, code
, "Cannot save dump schedule file");
177 afs_com_err(whoami
, 0, "Deletion is temporary - for this session only");
181 if (ctPtr
->lockHandle
!= 0)
182 bc_UnlockText(ctPtr
);
187 * Print out the dump schedule tree whose root is adump. Alevel should
188 * be passed in as 0, and is incremented for the recursive calls
190 * adump - ptr to the root node of a dump schedule
195 ListDumpSchedule(struct bc_dumpSchedule
*adump
, int alevel
)
198 struct bc_dumpSchedule
*child
;
200 /* sanity check for loops */
202 printf("backup: recursing listing dump schedule\n");
206 /* move to appropriate indentation level */
207 for (i
= 0; i
< alevel
; i
++)
210 /* name is a pathname style name, determine trailing name and only print
214 printf("/%s ", tailCompPtr(adump
->name
));
217 /* list expiration time */
218 switch (adump
->expType
) {
220 /* absolute expiration date. Never expires if date is 0 */
221 if (adump
->expDate
) {
222 time_t t
= adump
->expDate
;
223 printf("expires at %.24s", cTIME(&t
));
229 struct ktime_date kt
;
231 /* expiration date relative to the time that the dump is done */
232 LongTo_ktimeRelDate(adump
->expDate
, &kt
);
233 printf(" expires in %s", RelDatetoString(&kt
));
241 for (child
= adump
->firstChild
; child
; child
= child
->nextSibling
)
242 ListDumpSchedule(child
, alevel
+ 1);
247 /* bc_ListDumpScheduleCmd
248 * list the (internally held) dump schedule tree
254 bc_ListDumpScheduleCmd(struct cmd_syndesc
*as
, void *arock
)
258 struct bc_dumpSchedule
*tdump
;
260 /* first check to see if schedules must be updated */
261 code
= bc_UpdateDumpSchedule();
263 afs_com_err(whoami
, code
, "; Can't retrieve dump schedule");
267 /* go through entire list, displaying trees for root-level dump
270 for (tdump
= bc_globalConfig
->dsched
; tdump
; tdump
= tdump
->next
) {
271 /* if this is a root-level dump, show it and its kids */
273 ListDumpSchedule(tdump
, 0);
280 * Set/clear expiration date on existing dump node
282 * parm 0: list of dump names
283 * parm 1: expiration date (list)
287 bc_SetExpCmd(struct cmd_syndesc
*as
, void *arock
)
289 char *dname
; /* dump schedule name */
291 struct bc_dumpSchedule
*node
, *parent
;
292 afs_int32 expType
, expDate
;
293 udbClientTextP ctPtr
;
296 /* if an expiration date has been specified */
297 if (as
->parms
[1].items
) {
298 code
= bc_ParseExpiration(&as
->parms
[1], &expType
, &expDate
);
300 printf("Invalid expiration date syntax\n");
304 /* no expiration date specified */
306 expType
= BC_NO_EXPDATE
;
309 /* lock schedules and check validity */
310 ctPtr
= &bc_globalConfig
->configText
[TB_DUMPSCHEDULE
];
312 code
= bc_LockText(ctPtr
);
316 code
= bc_UpdateDumpSchedule();
318 afs_com_err(whoami
, code
, "; Can't retrieve dump schedule");
322 /* process each dump name using the expiration date computed above */
323 for (ti
= as
->parms
[0].items
; ti
!= 0; ti
= ti
->next
) {
324 /* get next dump name to process */
327 /* validate the name dump name length */
328 if (strlen(dname
) >= BU_MAX_DUMP_PATH
) {
330 afs_com_err(whoami
, 0, "Dump names must be < %d characters",
332 afs_com_err(whoami
, 0, "Dump %s not added", dname
);
336 code
= FindDump(bc_globalConfig
, dname
, &parent
, &node
);
338 afs_com_err(whoami
, 0, "Dump level %s not found", dname
);
342 node
->expDate
= expDate
;
343 node
->expType
= expType
;
346 code
= bc_SaveDumpSchedule();
348 afs_com_err(whoami
, code
, "Cannot save dump schedule");
349 afs_com_err(whoami
, 0,
350 "Expiration changes effective for this session only");
354 if (ctPtr
->lockHandle
)
355 bc_UnlockText(ctPtr
);
361 /* ------------------------------------
362 * general dump schedule handling routines
363 * ------------------------------------
367 bc_ParseDumpSchedule(void)
370 char dsname
[256], period
[64];
373 udbClientTextP ctPtr
;
374 struct bc_dumpSchedule
*tds
;
375 struct bc_dumpSchedule
**ppds
, *pds
;
376 afs_int32 expDate
, expType
;
380 /* initialize locally used variables */
381 ctPtr
= &bc_globalConfig
->configText
[TB_DUMPSCHEDULE
];
382 stream
= ctPtr
->textStream
;
384 if (ctPtr
->textSize
== 0) /* nothing defined yet */
388 return (BC_INTERNALERROR
);
392 /* check the magic number and version */
393 tp
= fgets(tbuffer
, sizeof(tbuffer
), stream
);
395 /* can't read first line - error */
396 return (BC_INTERNALERROR
);
398 afs_int32 dsmagic
, dsversion
;
400 /* read the first line, and then check magic # and version */
402 code
= sscanf(tbuffer
, "%d %d", &dsmagic
, &dsversion
);
404 || (dsmagic
!= BC_SCHEDULE_MAGIC
)
405 || (dsversion
!= BC_SCHEDULE_VERSION
)
407 /* invalid or unexpected header - error */
408 afs_com_err(whoami
, 0, "Unable to understand dump schedule file");
409 return (BC_INTERNALERROR
);
414 /* read all of the lines out */
415 tp
= fgets(tbuffer
, sizeof(tbuffer
), stream
);
417 break; /* hit eof? */
419 sscanf(tbuffer
, "%s %s %d %d", dsname
, period
, &expDate
,
422 afs_com_err(whoami
, 0,
423 "Syntax error in dump schedule file, line is: %s",
425 return (BC_INTERNALERROR
);
427 tds
= calloc(1, sizeof(struct bc_dumpSchedule
));
429 tds
->next
= (struct bc_dumpSchedule
*)0;
430 tds
->name
= strdup(dsname
);
432 tds
->expDate
= expDate
;
433 tds
->expType
= expType
;
435 /* find the end of the schedule list, and append the new item to it */
436 ppds
= &bc_globalConfig
->dsched
;
448 bc_SaveDumpSchedule(void)
450 struct bc_dumpSchedule
*tdump
;
451 udbClientTextP ctPtr
;
454 extern struct bc_config
*bc_globalConfig
;
456 /* setup the right ptr */
457 ctPtr
= &bc_globalConfig
->configText
[TB_DUMPSCHEDULE
];
460 if (ctPtr
->lockHandle
== 0)
461 return (BC_INTERNALERROR
);
463 /* truncate the file */
464 code
= ftruncate(fileno(ctPtr
->textStream
), 0);
468 rewind(ctPtr
->textStream
);
470 /* write the new information */
471 fprintf(ctPtr
->textStream
, "%d %d\n", BC_SCHEDULE_MAGIC
,
472 BC_SCHEDULE_VERSION
);
474 for (tdump
= bc_globalConfig
->dsched
; tdump
; tdump
= tdump
->next
) {
475 fprintf(ctPtr
->textStream
, "%s %s %d %d\n", tdump
->name
, "any",
476 tdump
->expDate
, tdump
->expType
);
479 if (ferror(ctPtr
->textStream
))
480 return (BC_INTERNALERROR
);
482 fflush(ctPtr
->textStream
); /* debug */
485 code
= bcdb_SaveTextFile(ctPtr
);
489 /* increment local version number */
490 ctPtr
->textVersion
++;
492 /* update locally stored file size */
493 ctPtr
->textSize
= filesize(ctPtr
->textStream
);
499 /* ------------------------------------
500 * misc. support routines - specific to dump schedules
501 * ------------------------------------
505 bc_UpdateDumpSchedule(void)
507 struct bc_dumpSchedule
*dumpPtr
, *nextDumpPtr
;
508 struct udbHandleS
*uhptr
= &udbHandle
;
509 udbClientTextP ctPtr
;
513 /* lock schedules and check validity */
514 ctPtr
= &bc_globalConfig
->configText
[TB_DUMPSCHEDULE
];
516 code
= bc_CheckTextVersion(ctPtr
);
517 if (code
!= BC_VERSIONMISMATCH
) {
518 ERROR(code
); /* Version matches or some other error */
521 /* Must update the dump schedules */
522 /* If we are not already locked, then lock it now */
523 if (!ctPtr
->lockHandle
) {
524 code
= bc_LockText(ctPtr
);
530 if (ctPtr
->textVersion
!= -1) {
531 printf("backup: obsolete dump schedule - updating\n");
533 /* clear all old schedule information */
534 dumpPtr
= bc_globalConfig
->dsched
;
536 nextDumpPtr
= dumpPtr
->next
;
538 dumpPtr
= nextDumpPtr
;
540 bc_globalConfig
->dsched
= 0;;
543 /* open a temp file to store the config text received from buserver *
544 * The open file stream is stored in ctPtr->textStream */
546 bc_openTextFile(ctPtr
,
548 tmpTextFileNames
[TB_DUMPSCHEDULE
][0]);
551 /* now get a fresh set of information from the database */
552 code
= bcdb_GetTextFile(ctPtr
);
556 /* fetch the version number */
558 ubik_BUDB_GetTextVersion(uhptr
->uh_client
, 0, ctPtr
->textType
,
559 &ctPtr
->textVersion
);
564 code
= bc_ParseDumpSchedule();
568 /* rebuild the tree */
569 code
= bc_ProcessDumpSchedule(bc_globalConfig
);
574 if (lock
&& ctPtr
->lockHandle
)
575 bc_UnlockText(ctPtr
);