Bug Summary

File:bucoord/vol_sets.c
Location:line 204, column 2
Description:Assigned value is always the same as the existing value

Annotated Source Code

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#include <afsconfig.h>
11#include <afs/param.h>
12#include <afs/stds.h>
13
14#include <roken.h>
15
16#include <afs/budb_client.h>
17#include <afs/cmd.h>
18#include <afs/com_err.h>
19#include <afs/bubasics.h>
20
21#include "bc.h"
22#include "error_macros.h"
23#include "bucoord_internal.h"
24#include "bucoord_prototypes.h"
25
26/* code to manage volumesets
27 * specific to the ubik database implementation
28 */
29
30extern struct bc_config *bc_globalConfig;
31extern struct udbHandleS udbHandle;
32extern char *whoami;
33
34static int ListVolSet(struct bc_volumeSet *aset);
35
36/* ------------------------------------
37 * command level routines
38 * ------------------------------------
39 */
40
41
42/* bc_AddVolEntryCmd
43 * add a volume (or volume expression) to a volume set
44 * params:
45 * parm 0 is vol set name.
46 * parm 1 is server name
47 * parm 2 is partition name
48 * parm 3 is volume regexp
49 */
50
51int
52bc_AddVolEntryCmd(struct cmd_syndesc *as, void *arock)
53{
54 int code;
55 char *volSetName, *serverName, *partitionName, *volRegExp;
56 udbClientTextP ctPtr;
57 struct bc_volumeSet *tset;
58
59 volSetName = as->parms[0].items->data;
60 serverName = as->parms[1].items->data;
61 partitionName = as->parms[2].items->data;
62 volRegExp = as->parms[3].items->data;
63
64 code = bc_UpdateVolumeSet();
65 if (code) {
66 afs_com_err(whoami, code, "; Can't retrieve volume sets");
67 return (code);
68 }
69
70 ctPtr = &bc_globalConfig->configText[TB_VOLUMESET1];
71
72 tset = bc_FindVolumeSet(bc_globalConfig, volSetName);
73 if (!tset) {
74 afs_com_err(whoami, code, "; Volume entry not added");
75 ERROR(code)do { code = code; goto error_exit; } while (0);
76 }
77
78 if (!(tset->flags & VSFLAG_TEMPORARY1)) {
79 code = bc_LockText(ctPtr);
80 if (code)
81 ERROR(code)do { code = code; goto error_exit; } while (0);
82 }
83
84 code = bc_UpdateVolumeSet();
85 if (code) {
86 afs_com_err(whoami, code, "; Can't retrieve volume sets");
87 return (code);
88 }
89
90 code =
91 bc_AddVolumeItem(bc_globalConfig, volSetName, serverName,
92 partitionName, volRegExp);
93 if (code) {
94 afs_com_err(whoami, code, "; Volume entry not added");
95 ERROR(code)do { code = code; goto error_exit; } while (0);
96 }
97
98 if (!(tset->flags & VSFLAG_TEMPORARY1)) {
99 code = bc_SaveVolumeSet();
100 if (code) {
101 afs_com_err(whoami, code, "Cannot save volume set file");
102 afs_com_err(whoami, 0,
103 "Changes are temporary - for this session only");
104 }
105 }
106
107 error_exit:
108 if (ctPtr->lockHandle)
109 bc_UnlockText(ctPtr);
110 return (code);
111}
112
113
114
115/* bc_AddVolSetCmd
116 * create a new volume set, writing out the new volumeset
117 * file in a safe manner
118 * params:
119 * name of new volume set
120 */
121
122int
123bc_AddVolSetCmd(struct cmd_syndesc *as, void *arock)
124{
125 /* parm 0 is vol set name */
126 int code;
127 struct cmd_item *ti;
128 udbClientTextP ctPtr;
129 afs_int32 flags;
130
131 /* lock schedules and check validity */
132 ctPtr = &bc_globalConfig->configText[TB_VOLUMESET1];
133
134 flags = (as->parms[1].items ? VSFLAG_TEMPORARY1 : 0);
135
136 /* Don't lock if adding a temporary volumeset */
137 if (!(flags & VSFLAG_TEMPORARY1)) {
138 code = bc_LockText(ctPtr);
139 if (code)
140 ERROR(code)do { code = code; goto error_exit; } while (0);
141 }
142
143 code = bc_UpdateVolumeSet();
144 if (code) {
145 afs_com_err(whoami, code, "; Can't retrieve volume sets");
146 return (code);
147 }
148
149 /* validate size of volumeset name */
150 code =
151 bc_CreateVolumeSet(bc_globalConfig, (ti = as->parms[0].items)->data,
152 flags);
153 if (code) {
154 if (code == -1)
155 afs_com_err(whoami, 0, "Volume set '%s' already exists", ti->data);
156 else
157 afs_com_err(whoami, 0, "Unknown problem");
158 } else if (!(flags & VSFLAG_TEMPORARY1)) {
159 code = bc_SaveVolumeSet();
160 if (code) {
161 afs_com_err(whoami, code, "Cannot save new volume set file");
162 afs_com_err(whoami, 0,
163 "Changes are temporary - for this session only");
164 }
165 }
166
167 error_exit:
168 if (ctPtr->lockHandle != 0)
169 bc_UnlockText(ctPtr);
170 return (code);
171}
172
173
174/* bc_DeleteVolEntryCmd
175 * delete a volume specification from a volume set
176 * params:
177 * parm 0 is vol set name
178 * parm 1 is entry # (integer, 1 based)
179 */
180
181int
182bc_DeleteVolEntryCmd(struct cmd_syndesc *as, void *arock)
183{
184 int code;
185 afs_int32 entry;
186 char *vsname;
187 udbClientTextP ctPtr;
188 struct bc_volumeSet *tset;
189
190 vsname = as->parms[0].items->data;
191
192 code = bc_UpdateVolumeSet();
193 if (code) {
1
Taking false branch
194 afs_com_err(whoami, code, "; Can't retrieve volume sets");
195 return (code);
196 }
197
198 /* lock schedules and check validity */
199 ctPtr = &bc_globalConfig->configText[TB_VOLUMESET1];
200
201 tset = bc_FindVolumeSet(bc_globalConfig, vsname);
202 if (!tset) {
2
Taking true branch
203 afs_com_err(whoami, 0, "No such volume set as '%s'", vsname);
204 ERROR(code)do { code = code; goto error_exit; } while (0);
3
Within the expansion of the macro 'ERROR':
a
Assigned value is always the same as the existing value
205 }
206
207 if (!(tset->flags & VSFLAG_TEMPORARY1)) {
208 code = bc_LockText(ctPtr);
209 if (code)
210 ERROR(code)do { code = code; goto error_exit; } while (0);
211 }
212
213 code = bc_UpdateVolumeSet();
214 if (code) {
215 afs_com_err(whoami, code, "; Can't retrieve volume sets");
216 return (code);
217 }
218
219 entry = bc_SafeATOI(as->parms[1].items->data);
220 if (entry < 0) {
221 afs_com_err(whoami, 0, "Can't parse entry number '%s' as decimal integer",
222 as->parms[1].items->data);
223 ERROR(BC_BADARG)do { code = (156288000L); goto error_exit; } while (0);
224 }
225
226 code = bc_DeleteVolumeItem(bc_globalConfig, vsname, entry);
227 if (code) {
228 if (code == -1) {
229 afs_com_err(whoami, 0, "No such volume set as '%s'", vsname);
230 } else if (code == -2) {
231 afs_com_err(whoami, 0,
232 "There aren't %d volume items for this volume set",
233 entry);
234 afs_com_err(whoami, 0,
235 "Use the 'listvolsets' command to examine the volume set");
236 }
237 ERROR(code)do { code = code; goto error_exit; } while (0);
238 }
239
240 if (!(tset->flags & VSFLAG_TEMPORARY1)) {
241 code = bc_SaveVolumeSet();
242 if (code == 0) {
243 printf("backup: deleted volume entry %d from volume set %s\n",
244 entry, vsname);
245 } else {
246 afs_com_err(whoami, code, "Cannot save volume set file");
247 afs_com_err(whoami, 0,
248 "Deletion is temporary - for this session only");
249 }
250 }
251
252 error_exit:
253 if (ctPtr->lockHandle != 0)
254 bc_UnlockText(ctPtr);
255 return (code);
256}
257
258
259
260
261/* bc_DeleteVolSetCmd
262 * delete a volume set, writing out a new configuration file when
263 * completed
264 * params:
265 * name of volumeset to delete
266 */
267
268int
269bc_DeleteVolSetCmd(struct cmd_syndesc *as, void *arock)
270{
271 /* parm 0 is vol set name */
272 int code;
273 struct cmd_item *ti;
274 udbClientTextP ctPtr;
275 afs_int32 c;
276 afs_int32 flags, tosave = 0;
277
278 /* lock schedules and check validity */
279 ctPtr = &bc_globalConfig->configText[TB_VOLUMESET1];
280
281 code = bc_LockText(ctPtr);
282 if (code)
283 ERROR(code)do { code = code; goto error_exit; } while (0);
284
285 code = bc_UpdateVolumeSet();
286 if (code) {
287 afs_com_err(whoami, code, "; Can't retrieve volume sets");
288 return (code);
289 }
290
291 for (ti = as->parms[0].items; ti; ti = ti->next) {
292 code = bc_DeleteVolumeSet(bc_globalConfig, ti->data, &flags);
293 if (code) {
294 if (code == -1)
295 afs_com_err(whoami, 0, "Can't find volume set '%s'", ti->data);
296 else
297 afs_com_err(whoami, code,
298 "; Unknown problem deleting volume set '%s'",
299 ti->data);
300 } else {
301 if (!(flags & VSFLAG_TEMPORARY1))
302 tosave = 1;
303 printf("backup: deleted volume set '%s'\n", ti->data);
304 }
305 }
306
307 /* now write out the file */
308 if (tosave) {
309 c = bc_SaveVolumeSet();
310 if (c) {
311 if (!code)
312 code = c;
313 afs_com_err(whoami, c, "Cannot save updated volume set file");
314 afs_com_err(whoami, 0, "Deletion effective for this session only");
315 }
316
317 }
318
319 error_exit:
320 if (ctPtr->lockHandle)
321 bc_UnlockText(ctPtr);
322 return (code);
323}
324
325
326static int
327ListVolSet(struct bc_volumeSet *aset)
328{
329 struct bc_volumeEntry *tentry;
330 int i;
331
332 printf("Volume set %s", aset->name);
333 if (aset->flags & VSFLAG_TEMPORARY1)
334 printf(" (temporary)");
335 printf(":\n");
336 i = 1;
337 for (tentry = aset->ventries; tentry; tentry = tentry->next, i++) {
338 printf(" Entry %3d: server %s, partition %s, volumes: %s\n", i,
339 tentry->serverName, tentry->partname, tentry->name);
340 }
341 return 0;
342}
343
344 /* bc_ListVolSetCmd
345 * list out all the information (?) about a volumeset or about all
346 * volumesets
347 * entry:
348 * optional parameter specifies a volumeset name
349 */
350
351int
352bc_ListVolSetCmd(struct cmd_syndesc *as, void *arock)
353{
354 /* parm 0 is optional volume set to display */
355 struct bc_volumeSet *tset;
356 struct cmd_item *ti;
357 int code = 0;
358
359 code = bc_UpdateVolumeSet();
360 if (code) {
361 afs_com_err(whoami, code, "; Can't retrieve volume sets");
362 return (code);
363 }
364
365 /* figure out volume set to list */
366 if ((ti = as->parms[0].items)) {
367 /* for each volume set in the command item list */
368 for (; ti; ti = ti->next) {
369 tset = bc_FindVolumeSet(bc_globalConfig, ti->data);
370 if (tset) {
371 ListVolSet(tset);
372 printf("\n");
373 } else {
374 afs_com_err(whoami, 0, "Can't find volume set '%s'", ti->data);
375 code = 1;
376 }
377 }
378 } else {
379 /* no command parameters specified, show entire list */
380 for (tset = bc_globalConfig->vset; tset; tset = tset->next) {
381 ListVolSet(tset);
382 printf("\n");
383 }
384 }
385
386 return code;
387}
388
389
390
391/* ------------------------------------
392 * support routines
393 * ------------------------------------
394 */
395
396int
397bc_ClearVolumeSets(void)
398{
399 struct bc_volumeSet *vsPtr, *vsNextPtr, **vsPrev;
400
401 extern struct bc_config *bc_globalConfig;
402
403 vsPrev = &(bc_globalConfig->vset);
404 for (vsPtr = bc_globalConfig->vset; vsPtr; vsPtr = vsNextPtr) {
405 vsNextPtr = vsPtr->next;
406
407 if (vsPtr->flags & VSFLAG_TEMPORARY1) { /* Skip temporary volumeSet */
408 vsPrev = &(vsPtr->next);
409 continue;
410 }
411
412 *vsPrev = vsPtr->next; /* Remove volumeSet from the chain */
413 FreeVolumeSet(vsPtr);
414 }
415 return (0);
416}
417
418/* bc_ParseVolumeSet
419 * Open up the volume set configuration file as specified in our argument,
420 * then parse the file to set up our internal representation.
421 * exit:
422 * 0 on successful processing,
423 * -1 otherwise.
424 */
425
426int
427bc_ParseVolumeSet(void)
428{
429 char tbuffer[1024]; /*Buffer for reading config file */
430 char vsname[256]; /*Volume set name */
431 char serverName[256]; /*Server name */
432 char partName[256]; /*Partition name */
433 struct bc_volumeEntry *tve; /*Ptr to generated volume spec struct */
434 struct bc_volumeSet *tvs = NULL((void *)0); /*Ptr to volume set struct */
435 struct bc_volumeEntry **ppve, *pve;
436 struct bc_volumeSet **ppvs, *pvs;
437 afs_int32 code; /*Generalized return code */
438 char *tp; /*Result of fgets(), malloc() */
439 int readHeader; /*Is next thing to read a volume set hdr? */
440
441 udbClientTextP ctPtr;
442 FILE *stream;
443
444 extern struct bc_config *bc_globalConfig;
445
446 ctPtr = &bc_globalConfig->configText[TB_VOLUMESET1];
447 stream = ctPtr->textStream;
448
449 /*
450 * Open up the volume set configuration file, fail if it can't be done.
451 */
452
453 if (ctPtr->textSize == 0) /* empty is ok */
454 return (0);
455
456 /* stream checks and initialization */
457 if (stream == NULL((void *)0))
458 return (BC_INTERNALERROR(156288014L));
459
460 rewind(stream);
461
462 readHeader = 1;
463 while (1) {
464 /* Read in and process the next line of the volume set description
465 * file.
466 */
467 tp = fgets(tbuffer, sizeof(tbuffer), stream);
468 if (!tp)
469 break;
470 if (readHeader) { /*r */
471 /*
472 * Scan a header entry.
473 */
474 readHeader = 0;
475 code = sscanf(tbuffer, "%s %s", serverName, vsname);
476 if ((code != 2)
477 || (strcmp(serverName, "volumeset") != 0)
478 ) {
479 afs_com_err(whoami, 0, "Bad volume header line: '%s'", tbuffer);
480 return (-1);
481 }
482
483 /* Create and fill in the volume set descriptor structure from
484 * the info just read placing it at the head of its queue in the
485 * global configuration structure.
486 */
487 tvs = (struct bc_volumeSet *)malloc(sizeof(struct bc_volumeSet));
488 memset(tvs, 0, sizeof(*tvs));
489 tvs->name = (char *)malloc(strlen(vsname) + 1);
490 strcpy(tvs->name, vsname);
491
492 /* append to the end */
493 for (ppvs = &bc_globalConfig->vset, pvs = *ppvs; pvs;
494 ppvs = &pvs->next, pvs = *ppvs);
495 *ppvs = tvs;
496 tvs->next = (struct bc_volumeSet *)0;
497 } /*r */
498 else { /*e */
499 /* Scan a volume name entry, which contains the server name,
500 * partition pattern, and volume pattern.
501 */
502 code = sscanf(tbuffer, "%s %s %s", serverName, partName, vsname);
503 if (code == 1 && strcmp(serverName, "end") == 0) {
504 /* This was really a line delimiting the current volume set.
505 * Next time around, we should try to read a header.
506 */
507 readHeader = 1;
508 continue;
509 }
510
511 /* The line just read in is a volume spec. Create a new volume
512 * spec record, then get the rest of the information regarding
513 * the host, and stuff everything into place.
514 */
515 tve = (struct bc_volumeEntry *)
516 malloc(sizeof(struct bc_volumeEntry));
517 if (!tve) {
518 afs_com_err(whoami, 0,
519 "Can't malloc() a new volume spec record!");
520 return (-1);
521 }
522 memset(tve, 0, sizeof(*tve));
523 if (bc_ParseHost(serverName, &(tve->server)))
524 afs_com_err(whoami, 0, "Can't get required info on host '%s'",
525 serverName);
526
527 /* The above code has filled in the server sockaddr, now fill in
528 * the rest of the fields.
529 */
530 tve->serverName = (char *)malloc(strlen(serverName) + 1);
531 if (!tve->serverName) {
532 afs_com_err(whoami, 0,
533 "Can't malloc() a new volume spec server name field!");
534 return (-1);
535 }
536 strcpy(tve->serverName, serverName);
537 tve->partname = (char *)malloc(strlen(partName) + 1);
538 if (!tve->partname) {
539 afs_com_err(whoami, 0,
540 "Can't malloc() a new volume spec partition pattern field!");
541 return (-1);
542 }
543 strcpy(tve->partname, partName);
544 code = bc_GetPartitionID(partName, &tve->partition);
545 if (code) {
546 afs_com_err(whoami, 0, "Can't parse partition '%s'", partName);
547 return -1;
548 }
549 tp = (char *)malloc(strlen(vsname) + 1);
550 if (!tp) {
551 afs_com_err(whoami, 0,
552 "Can't malloc() a new volume spec volume pattern field!");
553 return (-1);
554 }
555 strcpy(tp, vsname);
556 tve->name = tp;
557
558 /* Now, thread it onto the list of other volume spec entries for
559 * the current volume set.
560 */
561
562 for (ppve = &tvs->ventries, pve = *ppve; pve;
563 ppve = &pve->next, pve = *ppve);
564 *ppve = tve;
565 tve->next = (struct bc_volumeEntry *)0;
566 }
567 } /*forever loop */
568
569 /* If we hit an EOF in the middle of a volume set record, we bitch and
570 * moan.
571 */
572 if (!readHeader)
573 return (-1);
574
575 /*
576 * Well, we did it. Return successfully.
577 */
578 return (0);
579
580} /*bc_ParseVolumeSet */
581
582/* bc_SaveVolumeSet
583 * save the current volume set information to disk
584 */
585
586int
587bc_SaveVolumeSet(void)
588{
589 afs_int32 code = 0;
590 struct bc_volumeSet *tset;
591 struct bc_volumeEntry *tentry;
592
593 udbClientTextP ctPtr;
594 FILE *stream;
595
596 extern struct bc_config *bc_globalConfig;
597
598 ctPtr = &bc_globalConfig->configText[TB_VOLUMESET1];
599 stream = ctPtr->textStream;
600
601 /* must be locked */
602 if (ctPtr->lockHandle == 0)
603 return (BC_INTERNALERROR(156288014L));
604
605 /* truncate the file */
606 code = ftruncate(fileno(stream)(!__isthreaded ? ((stream)->_file) : (fileno)(stream)), 0);
607 if (code)
608 ERROR(errno)do { code = (* __error()); goto error_exit; } while (0);
609
610 rewind(stream);
611
612 /* now write the volumeset information */
613
614 for (tset = bc_globalConfig->vset; tset != 0; tset = tset->next) {
615 if (tset->flags & VSFLAG_TEMPORARY1)
616 continue; /* skip temporary entries */
617
618 fprintf(stream, "volumeset %s\n", tset->name);
619 for (tentry = tset->ventries; tentry; tentry = tentry->next) {
620 fprintf(stream, "%s %s %s\n", tentry->serverName,
621 tentry->partname, tentry->name);
622 }
623 fprintf(stream, "end\n");
624 }
625
626 if (ferror(stream)(!__isthreaded ? (((stream)->_flags & 0x0040) != 0) : (
ferror)(stream))
)
627 return (BC_INTERNALERROR(156288014L));
628
629 /* send to server */
630 code = bcdb_SaveTextFile(ctPtr);
631 if (code)
632 ERROR(code)do { code = code; goto error_exit; } while (0);
633
634 /* do this on bcdb_SaveTextFile */
635 /* increment local version number */
636 ctPtr->textVersion++;
637
638 /* update locally stored file size */
639 ctPtr->textSize = filesize(ctPtr->textStream);
640
641 error_exit:
642 return (code);
643}
644
645afs_int32
646bc_UpdateVolumeSet(void)
647{
648 struct udbHandleS *uhptr = &udbHandle;
649 udbClientTextP ctPtr;
650 afs_int32 code;
651 int lock = 0;
652
653 /* lock schedules and check validity */
654 ctPtr = &bc_globalConfig->configText[TB_VOLUMESET1];
655
656 /* Don't need a lock to check the version */
657 code = bc_CheckTextVersion(ctPtr);
658 if (code != BC_VERSIONMISMATCH(156288001L)) {
659 ERROR(code)do { code = code; goto error_exit; } while (0); /* version matches or some other error */
660 }
661
662 /* Must update the volume sets */
663 /* If no lock alredy taken, then lock it */
664 if (ctPtr->lockHandle == 0) {
665 code = bc_LockText(ctPtr);
666 if (code)
667 ERROR(code)do { code = code; goto error_exit; } while (0);
668 lock = 1;
669 }
670
671 if (ctPtr->textVersion != -1) {
672 printf("backup: obsolete volumesets - updating\n");
673 bc_ClearVolumeSets();
674 }
675
676 /* open a temp file to store the config text received from buserver *
677 * The open file stream is stored in ctPtr->textStream */
678 code =
679 bc_openTextFile(ctPtr,
680 &bc_globalConfig->tmpTextFileNames[TB_VOLUMESET1][0]);
681 if (code)
682 ERROR(code)do { code = code; goto error_exit; } while (0);
683 /* now get a fresh set of information from the database */
684 code = bcdb_GetTextFile(ctPtr);
685 if (code)
686 ERROR(code)do { code = code; goto error_exit; } while (0);
687
688 /* fetch the version number */
689 code =
690 ubik_BUDB_GetTextVersion(uhptr->uh_client, 0, ctPtr->textType,
691 &ctPtr->textVersion);
692 if (code)
693 ERROR(code)do { code = code; goto error_exit; } while (0);
694
695 /* parse the file */
696 code = bc_ParseVolumeSet();
697 if (code)
698 ERROR(code)do { code = code; goto error_exit; } while (0);
699
700 error_exit:
701 if (lock && ctPtr->lockHandle)
702 bc_UnlockText(ctPtr);
703 return (code);
704}