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)
63 /* clean up from previous invocation */
67 if(amandates_list != NULL)
69 amfree(g_amandates_file);
71 /* initialize state */
74 readonly = !open_readwrite;
76 amandates_list = NULL;
77 g_amandates_file = stralloc(amandates_file);
80 if (access(amandates_file,F_OK))
81 /* not yet existing */
82 if ( (rc = open(amandates_file,(O_CREAT|O_RDWR),0644)) != -1 )
83 /* open/create successfull */
87 amdf = fopen(amandates_file, "r+");
89 amdf = fopen(amandates_file, "r");
91 /* create it if we need to */
93 if(amdf == NULL && (errno == EINTR || errno == ENOENT) && open_readwrite)
94 amdf = fopen(amandates_file, "w");
100 rc = amflock(fileno(amdf), amandates_file);
102 rc = amroflock(fileno(amdf), amandates_file);
105 error("could not lock %s: %s", amandates_file, strerror(errno));
109 for(; (line = agets(amdf)) != NULL; free(line)) {
115 skip_whitespace(s, ch);
117 continue; /* no name field */
120 skip_quoted_string(s, ch);
121 s[-1] = '\0'; /* terminate the name */
122 name = unquote_string(qname);
124 skip_whitespace(s, ch);
125 if(ch == '\0' || sscanf(s - 1, "%d %ld", &level, &ldate) != 2) {
127 continue; /* no more fields */
130 if(level < 0 || level >= DUMP_LEVELS) {
135 enter_record(name, level, (time_t) ldate);
140 error("reading %s: %s", amandates_file, strerror(errno));
144 updated = 0; /* reset updated flag */
149 finish_amandates(void)
160 error("updated amandates after opening readonly");
165 for(amdp = amandates_list; amdp != NULL; amdp = amdp->next) {
166 for(level = 0; level < DUMP_LEVELS; level++) {
167 if(amdp->dates[level] == EPOCH) continue;
168 qname = quote_string(amdp->name);
169 fprintf(amdf, "%s %d %ld\n",
170 qname, level, (long) amdp->dates[level]);
176 if(amfunlock(fileno(amdf), g_amandates_file) == -1) {
177 error("could not unlock %s: %s", g_amandates_file, strerror(errno));
180 if (fclose(amdf) == EOF) {
181 error("error [closing %s: %s]", g_amandates_file, strerror(errno));
190 amandates_t *amdp, *nextp;
192 for(amdp = amandates_list; amdp != NULL; amdp = nextp) {
197 amandates_list = NULL;
205 amandates_t *prevp, *amdp;
208 (void)import; /* Quiet unused parameter warning */
212 amdp = amandates_list;
213 while (amdp != NULL) {
214 if ((rc = strcmp(name, amdp->name)) <= 0)
219 if (!(amdp && (rc == 0))) {
220 amandates_t *newp = alloc(SIZEOF(amandates_t));
221 newp->name = stralloc(name);
222 for (level = 0; level < DUMP_LEVELS; level++)
223 newp->dates[level] = EPOCH;
226 #ifndef __lint /* Remove complaint about NULL pointer assignment */
232 amandates_list = newp;
234 import_dumpdates(newp);
244 return lookup(name, 1);
256 amdp = lookup(name, 0);
258 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
259 qname = quote_string(name);
260 /* this is not allowed, but we can ignore it */
261 dbprintf(("amandates botch: %s lev %d: new dumpdate %ld old %ld\n",
262 qname, level, (long) dumpdate, (long) amdp->dates[level]));
267 amdp->dates[level] = dumpdate;
282 amdp = lookup(name, 1);
284 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
285 /* this is not allowed, but we can ignore it */
286 qname = quote_string(name);
287 dbprintf(("amandates updateone: %s lev %d: new dumpdate %ld old %ld",
288 name, level, (long) dumpdate, (long) amdp->dates[level]));
293 amdp->dates[level] = dumpdate;
298 /* -------------------------- */
313 devname = amname_to_devname(amdp->name);
315 if((dumpdf = fopen("/var/lib/dumpdates", "r")) == NULL) {
320 for(; (line = agets(dumpdf)) != NULL; free(line)) {
326 skip_whitespace(s, ch);
328 continue; /* no fname field */
331 skip_non_whitespace(s, ch);
332 s[-1] = '\0'; /* terminate fname */
334 skip_whitespace(s, ch);
335 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
336 continue; /* no level field */
340 skip_whitespace(s, ch);
342 continue; /* no dumpdate field */
344 dumpdate = unctime(s-1);
346 if(strcmp(fname, devname) != 0 || level < 0 || level >= DUMP_LEVELS) {
350 if(dumpdate != -1 && dumpdate > amdp->dates[level]) {
351 if(!readonly) updated = 1;
352 amdp->dates[level] = dumpdate;