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.21 2006/07/25 18:35:21 martinea Exp $
29 * manage amandates file, that mimics /var/lib/dumpdates, but stores
37 #include "amandates.h"
39 static amandates_t *amandates_list = NULL;
40 static FILE *amdf = NULL;
41 static int updated, readonly;
42 static char *g_amandates_file = NULL;
43 static void import_dumpdates(amandates_t *);
44 static void enter_record(char *, int , time_t);
45 static amandates_t *lookup(char *name, int import);
60 if (amandates_file == NULL) {
65 /* clean up from previous invocation */
69 if(amandates_list != NULL)
71 amfree(g_amandates_file);
73 /* initialize state */
76 readonly = !open_readwrite;
78 amandates_list = NULL;
79 g_amandates_file = stralloc(amandates_file);
82 if (access(amandates_file,F_OK))
83 /* not yet existing */
84 if ( (rc = open(amandates_file,(O_CREAT|O_RDWR),0644)) != -1 )
85 /* open/create successfull */
89 amdf = fopen(amandates_file, "r+");
91 amdf = fopen(amandates_file, "r");
93 /* create it if we need to */
95 if(amdf == NULL && (errno == EINTR || errno == ENOENT) && open_readwrite)
96 amdf = fopen(amandates_file, "w");
102 rc = amflock(fileno(amdf), amandates_file);
104 rc = amroflock(fileno(amdf), amandates_file);
107 error(_("could not lock %s: %s"), amandates_file, strerror(errno));
111 for(; (line = agets(amdf)) != NULL; free(line)) {
117 skip_whitespace(s, ch);
119 continue; /* no name field */
122 skip_quoted_string(s, ch);
123 s[-1] = '\0'; /* terminate the name */
124 name = unquote_string(qname);
126 skip_whitespace(s, ch);
127 if(ch == '\0' || sscanf(s - 1, "%d %ld", &level, &ldate) != 2) {
129 continue; /* no more fields */
132 if(level < 0 || level >= DUMP_LEVELS) {
137 enter_record(name, level, (time_t) ldate);
142 error(_("reading %s: %s"), amandates_file, strerror(errno));
146 updated = 0; /* reset updated flag */
151 finish_amandates(void)
162 error(_("updated amandates after opening readonly"));
167 for(amdp = amandates_list; amdp != NULL; amdp = amdp->next) {
168 for(level = 0; level < DUMP_LEVELS; level++) {
169 if(amdp->dates[level] == EPOCH) continue;
170 qname = quote_string(amdp->name);
171 g_fprintf(amdf, "%s %d %ld\n",
172 qname, level, (long) amdp->dates[level]);
178 if(amfunlock(fileno(amdf), g_amandates_file) == -1) {
179 error(_("could not unlock %s: %s"), g_amandates_file, strerror(errno));
182 if (fclose(amdf) == EOF) {
183 error(_("error [closing %s: %s]"), g_amandates_file, strerror(errno));
192 amandates_t *amdp, *nextp;
194 for(amdp = amandates_list; amdp != NULL; amdp = nextp) {
199 amandates_list = NULL;
207 amandates_t *prevp, *amdp;
210 (void)import; /* Quiet unused parameter warning */
214 amdp = amandates_list;
215 while (amdp != NULL) {
216 if ((rc = strcmp(name, amdp->name)) <= 0)
221 if (!(amdp && (rc == 0))) {
222 amandates_t *newp = alloc(SIZEOF(amandates_t));
223 newp->name = stralloc(name);
224 for (level = 0; level < DUMP_LEVELS; level++)
225 newp->dates[level] = EPOCH;
228 #ifndef __lint /* Remove complaint about NULL pointer assignment */
234 amandates_list = newp;
236 import_dumpdates(newp);
246 return lookup(name, 1);
258 amdp = lookup(name, 0);
260 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
261 qname = quote_string(name);
262 /* this is not allowed, but we can ignore it */
263 dbprintf(_("amandates botch: %s lev %d: new dumpdate %ld old %ld\n"),
264 qname, level, (long) dumpdate, (long) amdp->dates[level]);
269 amdp->dates[level] = dumpdate;
284 amdp = lookup(name, 1);
286 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
287 /* this is not allowed, but we can ignore it */
288 qname = quote_string(name);
289 dbprintf(_("amandates updateone: %s lev %d: new dumpdate %ld old %ld"),
290 name, level, (long) dumpdate, (long) amdp->dates[level]);
295 amdp->dates[level] = dumpdate;
300 /* -------------------------- */
315 devname = amname_to_devname(amdp->name);
317 if((dumpdf = fopen("/var/lib/dumpdates", "r")) == NULL) {
322 for(; (line = agets(dumpdf)) != NULL; free(line)) {
328 skip_whitespace(s, ch);
330 continue; /* no fname field */
333 skip_non_whitespace(s, ch);
334 s[-1] = '\0'; /* terminate fname */
336 skip_whitespace(s, ch);
337 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
338 continue; /* no level field */
342 skip_whitespace(s, ch);
344 continue; /* no dumpdate field */
346 dumpdate = unctime(s-1);
348 if(strcmp(fname, devname) != 0 || level < 0 || level >= DUMP_LEVELS) {
352 if(dumpdate != -1 && dumpdate > amdp->dates[level]) {
353 if(!readonly) updated = 1;
354 amdp->dates[level] = dumpdate;