2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: amandates.c,v 1.16 2003/10/22 17:43:20 martinea Exp $
29 * manage amandates file, that mimics /var/lib/dumpdates, but stores
36 #include "amandates.h"
38 static amandates_t *amandates_list = NULL;
39 static FILE *amdf = NULL;
40 static int updated, readonly;
41 static void import_dumpdates P((amandates_t *));
42 static void enter_record P((char *, int , time_t));
43 static amandates_t *lookup P((char *name, int import));
45 int start_amandates(open_readwrite)
50 char *line = NULL, *name = NULL;
54 /* clean up from previous invocation */
58 if(amandates_list != NULL)
61 /* initialize state */
64 readonly = !open_readwrite;
66 amandates_list = NULL;
70 if (access(AMANDATES_FILE,F_OK))
71 /* not yet existing */
72 if ( (rc = open(AMANDATES_FILE,(O_CREAT|O_RDWR),0644)) != -1 )
73 /* open/create successfull */
77 amdf = fopen(AMANDATES_FILE, "r+");
79 amdf = fopen(AMANDATES_FILE, "r");
81 /* create it if we need to */
83 if(amdf == NULL && (errno == EINTR || errno == ENOENT) && open_readwrite)
84 amdf = fopen(AMANDATES_FILE, "w");
90 rc = amflock(fileno(amdf), "amandates");
92 rc = amroflock(fileno(amdf), "amandates");
95 error("could not lock %s: %s", AMANDATES_FILE, strerror(errno));
97 for(; (line = agets(amdf)) != NULL; free(line)) {
101 skip_whitespace(s, ch);
103 continue; /* no name field */
106 skip_non_whitespace(s, ch);
107 s[-1] = '\0'; /* terminate the name */
109 skip_whitespace(s, ch);
110 if(ch == '\0' || sscanf(s - 1, "%d %ld", &level, &ldate) != 2) {
111 continue; /* no more fields */
114 if(level < 0 || level >= DUMP_LEVELS) {
118 enter_record(name, level, (time_t) ldate);
122 error("reading %s: %s", AMANDATES_FILE, strerror(errno));
124 updated = 0; /* reset updated flag */
128 void finish_amandates()
138 error("updated amandates after opening readonly");
141 for(amdp = amandates_list; amdp != NULL; amdp = amdp->next) {
142 for(level = 0; level < DUMP_LEVELS; level++) {
143 if(amdp->dates[level] == EPOCH) continue;
144 fprintf(amdf, "%s %d %ld\n",
145 amdp->name, level, (long) amdp->dates[level]);
150 if(amfunlock(fileno(amdf), "amandates") == -1)
151 error("could not unlock %s: %s", AMANDATES_FILE, strerror(errno));
152 if (fclose(amdf) == EOF)
153 error("error [closing %s: %s]", AMANDATES_FILE, strerror(errno));
157 void free_amandates()
159 amandates_t *amdp, *nextp;
161 for(amdp = amandates_list; amdp != NULL; amdp = nextp) {
166 amandates_list = NULL;
169 static amandates_t *lookup(name, import)
173 amandates_t *prevp, *amdp, *newp;
178 for(prevp=NULL,amdp=amandates_list;amdp!=NULL;prevp=amdp,amdp=amdp->next)
179 if((rc = strcmp(name, amdp->name)) <= 0)
185 newp = alloc(sizeof(amandates_t));
186 newp->name = stralloc(name);
187 for(level = 0; level < DUMP_LEVELS; level++)
188 newp->dates[level] = EPOCH;
190 if(prevp) prevp->next = newp;
191 else amandates_list = newp;
193 import_dumpdates(newp);
198 amandates_t *amandates_lookup(name)
201 return lookup(name, 1);
204 static void enter_record(name, level, dumpdate)
211 amdp = lookup(name, 0);
213 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
214 /* this is not allowed, but we can ignore it */
215 dbprintf(("amandates botch: %s lev %d: new dumpdate %ld old %ld\n",
216 name, level, (long) dumpdate, (long) amdp->dates[level]));
220 amdp->dates[level] = dumpdate;
224 void amandates_updateone(name, level, dumpdate)
233 amdp = lookup(name, 1);
235 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
236 /* this is not allowed, but we can ignore it */
237 dbprintf(("amandates updateone: %s lev %d: new dumpdate %ld old %ld",
238 name, level, (long) dumpdate, (long) amdp->dates[level]));
242 amdp->dates[level] = dumpdate;
247 /* -------------------------- */
249 static void import_dumpdates(amdp)
252 char *devname = NULL, *line = NULL, *fname = NULL;
259 devname = amname_to_devname(amdp->name);
261 if((dumpdf = fopen("/var/lib/dumpdates", "r")) == NULL) {
266 for(; (line = agets(dumpdf)) != NULL; free(line)) {
270 skip_whitespace(s, ch);
272 continue; /* no fname field */
275 skip_non_whitespace(s, ch);
276 s[-1] = '\0'; /* terminate fname */
278 skip_whitespace(s, ch);
279 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
280 continue; /* no level field */
284 skip_whitespace(s, ch);
286 continue; /* no dumpdate field */
288 dumpdate = unctime(s-1);
290 if(strcmp(fname, devname) != 0 || level < 0 || level >= DUMP_LEVELS) {
294 if(dumpdate != -1 && dumpdate > amdp->dates[level]) {
295 if(!readonly) updated = 1;
296 amdp->dates[level] = dumpdate;