bucoord: Set but not used variables
[openafs.git] / src / bucoord / dump_sched.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 /*
11  * ALL RIGHTS RESERVED
12  */
13
14 #include <sys/types.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20
21 #ifdef AFS_NT40_ENV
22 #include <winsock2.h>
23 #else
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <netdb.h>
27 #endif
28 #include <errno.h>
29 #include <afs/ktime.h>
30 #include <afs/budb_client.h>
31 #include <afs/cmd.h>
32 #include <afs/com_err.h>
33 #include <afs/bubasics.h>
34 #include "bc.h"
35 #include "error_macros.h"
36 #include "bucoord_internal.h"
37 #include "bucoord_prototypes.h"
38
39 /* code to manage dump schedules
40  * specific to the ubik database implementation
41  */
42
43 extern struct bc_config *bc_globalConfig;
44 extern struct udbHandleS udbHandle;
45 extern char *whoami;
46
47 static int ListDumpSchedule(struct bc_dumpSchedule *adump, int alevel);
48
49 /* ------------------------------------
50  * command level routines
51  * ------------------------------------
52  */
53
54 /* bc_AddDumpCmd
55  *      add a dump schedule
56  * params:
57  *      parm 0: list of dump names
58  *      parm 1: expiration date (list)
59  */
60
61 int
62 bc_AddDumpCmd(struct cmd_syndesc *as, void *arock)
63 {
64     char *dname;        /* dump schedule name */
65     int code;
66     afs_int32 expType, expDate;
67     struct cmd_item *ti;
68     udbClientTextP ctPtr;
69
70     /* if an expiration date has been specified */
71     if (as->parms[1].items) {
72         code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
73         if (code) {
74             printf("Invalid expiration date syntax\n");
75             return (1);
76         }
77     } else {
78         /* no expiration date specified */
79         expDate = 0;
80         expType = BC_NO_EXPDATE;
81     }
82
83     /* lock schedules and check validity */
84     ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
85
86     code = bc_LockText(ctPtr);
87     if (code)
88         ERROR(code);
89
90     code = bc_UpdateDumpSchedule();
91     if (code) {
92         afs_com_err(whoami, code, "; Can't retrieve dump schedule");
93         return (code);
94     }
95
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 */
99         dname = ti->data;
100
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",
104                     BU_MAX_DUMP_PATH);
105             afs_com_err(whoami, 0, "Dump %s not added", dname);
106             code = -1;
107             continue;
108         }
109
110         code =
111             bc_CreateDumpSchedule(bc_globalConfig, dname, expDate, expType);
112         if (code) {
113             if (code == -1)
114                 afs_com_err(whoami, 0, "Dump already exists");
115             else if (code == -2)
116                 afs_com_err(whoami, 0, "Invalid path name '%s'", dname);
117             else if (code == -3)
118                 afs_com_err(whoami, 0, "Name specification error");
119             else
120                 afs_com_err(whoami, code, "; Failed to create dump schedule");
121             continue;
122         }
123
124         /* save the new schedule item */
125         code = bc_SaveDumpSchedule();
126         if (code) {
127             afs_com_err(whoami, code, "Cannot save dump schedule");
128             afs_com_err(whoami, 0,
129                     "Changes are temporary - for this session only");
130             break;
131         }
132
133         afs_com_err(whoami, 0, "Created new dump schedule %s", dname);
134     }
135
136   error_exit:
137     if (ctPtr->lockHandle)
138         bc_UnlockText(ctPtr);
139     return (code);
140 }
141
142
143 /* bc_DeleteDumpCmd
144  *      delete a dump schedule
145  */
146
147 int
148 bc_DeleteDumpCmd(struct cmd_syndesc *as, void *arock)
149 {
150     /* parm 0 is vol set name
151      * parm 1 is dump schedule name
152      */
153     char *dname;
154     int code;
155     udbClientTextP ctPtr;
156
157     /* lock schedules and check validity */
158     ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
159
160     code = bc_LockText(ctPtr);
161     if (code)
162         ERROR(code);
163
164     code = bc_UpdateDumpSchedule();
165     if (code) {
166         afs_com_err(whoami, code, "; Can't retrieve dump schedule");
167         return (code);
168     }
169
170     dname = as->parms[0].items->data;
171
172     code = bc_DeleteDumpSchedule(bc_globalConfig, dname);
173     if (code) {
174         if (code == -1)
175             afs_com_err(whoami, 0, "No such dump as %s", dname);
176         else
177             afs_com_err(whoami, code, "; Failed to delete dump schedule");
178         goto error_exit;
179     }
180
181     code = bc_SaveDumpSchedule();
182     if (code == 0)
183         printf("backup: deleted dump schedule %s\n", dname);
184     else {
185         afs_com_err(whoami, code, "Cannot save dump schedule file");
186         afs_com_err(whoami, 0, "Deletion is temporary - for this session only");
187     }
188
189   error_exit:
190     if (ctPtr->lockHandle != 0)
191         bc_UnlockText(ctPtr);
192     return code;
193 }
194
195 /* ListDumpSchedule
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
198  * entry:
199  *      adump - ptr to the root node of a dump schedule
200  *      alevel - 0
201  */
202
203 static int
204 ListDumpSchedule(struct bc_dumpSchedule *adump, int alevel)
205 {
206     int i;
207     struct bc_dumpSchedule *child;
208
209     /* sanity check for loops */
210     if (alevel > 100) {
211         printf("backup: recursing listing dump schedule\n");
212         return -1;
213     }
214
215     /* move to appropriate indentation level */
216     for (i = 0; i < alevel; i++)
217         printf("    ");
218
219     /* name is a pathname style name, determine trailing name and only print
220      * it
221      */
222
223     printf("/%s ", tailCompPtr(adump->name));
224
225
226     /* list expiration time */
227     switch (adump->expType) {
228     case BC_ABS_EXPDATE:
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));
233         }
234         break;
235
236     case BC_REL_EXPDATE:
237         {
238             struct ktime_date kt;
239
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));
243         }
244         break;
245
246     default:
247         break;
248     }
249     printf("\n");
250     for (child = adump->firstChild; child; child = child->nextSibling)
251         ListDumpSchedule(child, alevel + 1);
252
253     return 0;
254 }
255
256 /* bc_ListDumpScheduleCmd
257  *      list the (internally held) dump schedule tree
258  * parameters:
259  *      ignored
260  */
261
262 int
263 bc_ListDumpScheduleCmd(struct cmd_syndesc *as, void *arock)
264 {
265     /* no parms */
266     int code;
267     struct bc_dumpSchedule *tdump;
268
269     /* first check to see if schedules must be updated */
270     code = bc_UpdateDumpSchedule();
271     if (code) {
272         afs_com_err(whoami, code, "; Can't retrieve dump schedule");
273         return (code);
274     }
275
276     /* go through entire list, displaying trees for root-level dump
277      * schedules
278      */
279     for (tdump = bc_globalConfig->dsched; tdump; tdump = tdump->next) {
280         /* if this is a root-level dump, show it and its kids */
281         if (!tdump->parent)
282             ListDumpSchedule(tdump, 0);
283     }
284     return 0;
285 }
286
287
288 /* bc_SetExpCmd
289  *      Set/clear expiration date on existing dump node
290  * params:
291  *      parm 0: list of dump names
292  *      parm 1: expiration date (list)
293  */
294
295 int
296 bc_SetExpCmd(struct cmd_syndesc *as, void *arock)
297 {
298     char *dname;        /* dump schedule name */
299     struct cmd_item *ti;
300     struct bc_dumpSchedule *node, *parent;
301     afs_int32 expType, expDate;
302     udbClientTextP ctPtr;
303     int code;
304
305     /* if an expiration date has been specified */
306     if (as->parms[1].items) {
307         code = bc_ParseExpiration(&as->parms[1], &expType, &expDate);
308         if (code) {
309             printf("Invalid expiration date syntax\n");
310             return (1);
311         }
312     } else {
313         /* no expiration date specified */
314         expDate = 0;
315         expType = BC_NO_EXPDATE;
316     }
317
318     /* lock schedules and check validity */
319     ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
320
321     code = bc_LockText(ctPtr);
322     if (code)
323         ERROR(code);
324
325     code = bc_UpdateDumpSchedule();
326     if (code) {
327         afs_com_err(whoami, code, "; Can't retrieve dump schedule");
328         return (code);
329     }
330
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 */
334         dname = ti->data;
335
336         /* validate the name dump name length */
337         if (strlen(dname) >= BU_MAX_DUMP_PATH) {
338             code = -1;
339             afs_com_err(whoami, 0, "Dump names must be < %d characters",
340                     BU_MAX_DUMP_PATH);
341             afs_com_err(whoami, 0, "Dump %s not added", dname);
342             continue;
343         }
344
345         code = FindDump(bc_globalConfig, dname, &parent, &node);
346         if (code) {
347             afs_com_err(whoami, 0, "Dump level %s not found", dname);
348             continue;
349         }
350
351         node->expDate = expDate;
352         node->expType = expType;
353     }
354
355     code = bc_SaveDumpSchedule();
356     if (code) {
357         afs_com_err(whoami, code, "Cannot save dump schedule");
358         afs_com_err(whoami, 0,
359                 "Expiration changes effective for this session only");
360     }
361
362   error_exit:
363     if (ctPtr->lockHandle)
364         bc_UnlockText(ctPtr);
365     return (code);
366 }
367
368
369
370 /* ------------------------------------
371  * general dump schedule handling routines
372  * ------------------------------------
373  */
374
375 int
376 bc_ParseDumpSchedule(void)
377 {
378     char tbuffer[1024];
379     char dsname[256], period[64];
380     char *tp;
381     afs_int32 code;
382     udbClientTextP ctPtr;
383     struct bc_dumpSchedule *tds;
384     struct bc_dumpSchedule **ppds, *pds;
385     afs_int32 expDate, expType;
386
387     FILE *stream;
388
389     /* initialize locally used variables */
390     ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
391     stream = ctPtr->textStream;
392
393     if (ctPtr->textSize == 0)   /* nothing defined yet */
394         return (0);
395
396     if (stream == NULL)
397         return (BC_INTERNALERROR);
398
399     rewind(stream);
400
401     /* check the magic number and version */
402     tp = fgets(tbuffer, sizeof(tbuffer), stream);
403     if (tp == 0)
404         /* can't read first line - error */
405         return (BC_INTERNALERROR);
406     else {
407         afs_int32 dsmagic, dsversion;
408
409         /* read the first line, and then check magic # and version */
410
411         code = sscanf(tbuffer, "%d %d", &dsmagic, &dsversion);
412         if ((code != 2)
413             || (dsmagic != BC_SCHEDULE_MAGIC)
414             || (dsversion != BC_SCHEDULE_VERSION)
415             ) {
416             /* invalid or unexpected header - error */
417             afs_com_err(whoami, 0, "Unable to understand dump schedule file");
418             return (BC_INTERNALERROR);
419         }
420     }
421
422     while (1) {
423         /* read all of the lines out */
424         tp = fgets(tbuffer, sizeof(tbuffer), stream);
425         if (tp == 0)
426             break;              /* hit eof? */
427         code =
428             sscanf(tbuffer, "%s %s %d %d", dsname, period, &expDate,
429                    &expType);
430         if (code != 4) {
431             afs_com_err(whoami, 0,
432                     "Syntax error in dump schedule file, line is: %s",
433                     tbuffer);
434             return (BC_INTERNALERROR);
435         }
436         tds =
437             (struct bc_dumpSchedule *)malloc(sizeof(struct bc_dumpSchedule));
438         memset(tds, 0, sizeof(*tds));
439
440         tds->next = (struct bc_dumpSchedule *)0;
441         tds->name = (char *)malloc(strlen(dsname) + 1);
442         strcpy(tds->name, dsname);
443
444         tds->expDate = expDate;
445         tds->expType = expType;
446
447         /* find the end of the schedule list, and append the new item to it */
448         ppds = &bc_globalConfig->dsched;
449         pds = *ppds;
450         while (pds != 0) {
451             ppds = &pds->next;
452             pds = *ppds;
453         }
454         *ppds = tds;
455     }
456     return 0;
457 }
458
459 int
460 bc_SaveDumpSchedule(void)
461 {
462     struct bc_dumpSchedule *tdump;
463     udbClientTextP ctPtr;
464     afs_int32 code = 0;
465
466     extern struct bc_config *bc_globalConfig;
467
468     /* setup the right ptr */
469     ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
470
471     /* must be locked */
472     if (ctPtr->lockHandle == 0)
473         return (BC_INTERNALERROR);
474
475     /* truncate the file */
476     code = ftruncate(fileno(ctPtr->textStream), 0);
477     if (code)
478         ERROR(errno);
479
480     rewind(ctPtr->textStream);
481
482     /* write the new information */
483     fprintf(ctPtr->textStream, "%d %d\n", BC_SCHEDULE_MAGIC,
484             BC_SCHEDULE_VERSION);
485
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);
489     }
490
491     if (ferror(ctPtr->textStream))
492         return (BC_INTERNALERROR);
493
494     fflush(ctPtr->textStream);  /* debug */
495
496     /* send to server */
497     code = bcdb_SaveTextFile(ctPtr);
498     if (code)
499         ERROR(code);
500
501     /* increment local version number */
502     ctPtr->textVersion++;
503
504     /* update locally stored file size */
505     ctPtr->textSize = filesize(ctPtr->textStream);
506   error_exit:
507     return (code);
508 }
509
510
511 /* ------------------------------------
512  * misc. support routines - specific to dump schedules
513  * ------------------------------------
514  */
515
516 afs_int32
517 bc_UpdateDumpSchedule(void)
518 {
519     struct bc_dumpSchedule *dumpPtr, *nextDumpPtr;
520     struct udbHandleS *uhptr = &udbHandle;
521     udbClientTextP ctPtr;
522     afs_int32 code;
523     int lock = 0;
524
525     /* lock schedules and check validity */
526     ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE];
527
528     code = bc_CheckTextVersion(ctPtr);
529     if (code != BC_VERSIONMISMATCH) {
530         ERROR(code);            /* Version matches or some other error */
531     }
532
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);
537         if (code)
538             ERROR(code);
539         lock = 1;
540     }
541
542     if (ctPtr->textVersion != -1) {
543         printf("backup: obsolete dump schedule - updating\n");
544
545         /* clear all old schedule information */
546         dumpPtr = bc_globalConfig->dsched;
547         while (dumpPtr) {
548             nextDumpPtr = dumpPtr->next;
549             free(dumpPtr);
550             dumpPtr = nextDumpPtr;
551         }
552         bc_globalConfig->dsched = 0;;
553     }
554
555     /* open a temp file to store the config text received from buserver *
556      * The open file stream is stored in ctPtr->textStream */
557     code =
558         bc_openTextFile(ctPtr,
559                         &bc_globalConfig->
560                         tmpTextFileNames[TB_DUMPSCHEDULE][0]);
561     if (code)
562         ERROR(code);
563     /* now get a fresh set of information from the database */
564     code = bcdb_GetTextFile(ctPtr);
565     if (code)
566         ERROR(code);
567
568     /* fetch the version number */
569     code =
570         ubik_BUDB_GetTextVersion(uhptr->uh_client, 0, ctPtr->textType,
571                   &ctPtr->textVersion);
572     if (code)
573         ERROR(code);
574
575     /* parse the file */
576     code = bc_ParseDumpSchedule();
577     if (code)
578         ERROR(code);
579
580     /* rebuild the tree */
581     code = bc_ProcessDumpSchedule(bc_globalConfig);
582     if (code)
583         ERROR(code);
584
585   error_exit:
586     if (lock && ctPtr->lockHandle)
587         bc_UnlockText(ctPtr);
588     return (code);
589 }
590