2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
4 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
28 * $Id: amandates.c,v 1.21 2006/07/25 18:35:21 martinea Exp $
30 * manage amandates file, that mimics /etc/dumpdates, but stores
38 #include "amandates.h"
40 static amandates_t *amandates_list = NULL;
41 static FILE *amdf = NULL;
42 static int updated, readonly;
43 static char *g_amandates_file = NULL;
44 static void import_dumpdates(amandates_t *);
45 static void enter_record(char *, int , time_t);
46 static amandates_t *lookup(char *name, int import);
61 if (amandates_file == NULL) {
66 /* clean up from previous invocation */
70 if(amandates_list != NULL)
72 amfree(g_amandates_file);
74 /* initialize state */
77 readonly = !open_readwrite;
79 amandates_list = NULL;
80 g_amandates_file = stralloc(amandates_file);
83 if (access(amandates_file,F_OK))
84 /* not yet existing */
85 if ( (rc = open(amandates_file,(O_CREAT|O_RDWR),0644)) != -1 )
86 /* open/create successfull */
90 amdf = fopen(amandates_file, "r+");
92 amdf = fopen(amandates_file, "r");
94 /* create it if we need to */
96 if(amdf == NULL && (errno == EINTR || errno == ENOENT) && open_readwrite)
97 amdf = fopen(amandates_file, "w");
103 rc = amflock(fileno(amdf), amandates_file);
105 rc = amroflock(fileno(amdf), amandates_file);
108 error(_("could not lock %s: %s"), amandates_file, strerror(errno));
112 for(; (line = agets(amdf)) != NULL; free(line)) {
118 skip_whitespace(s, ch);
120 continue; /* no name field */
123 skip_quoted_string(s, ch);
124 s[-1] = '\0'; /* terminate the name */
125 name = unquote_string(qname);
127 skip_whitespace(s, ch);
128 if(ch == '\0' || sscanf(s - 1, "%d %ld", &level, &ldate) != 2) {
130 continue; /* no more fields */
133 if(level < 0 || level >= DUMP_LEVELS) {
138 enter_record(name, level, (time_t) ldate);
143 error(_("reading %s: %s"), amandates_file, strerror(errno));
147 updated = 0; /* reset updated flag */
152 finish_amandates(void)
163 error(_("updated amandates after opening readonly"));
168 for(amdp = amandates_list; amdp != NULL; amdp = amdp->next) {
169 for(level = 0; level < DUMP_LEVELS; level++) {
170 if(amdp->dates[level] == EPOCH) continue;
171 qname = quote_string(amdp->name);
172 g_fprintf(amdf, "%s %d %ld\n",
173 qname, level, (long) amdp->dates[level]);
179 if(amfunlock(fileno(amdf), g_amandates_file) == -1) {
180 error(_("could not unlock %s: %s"), g_amandates_file, strerror(errno));
183 if (fclose(amdf) == EOF) {
184 error(_("error [closing %s: %s]"), g_amandates_file, strerror(errno));
193 amandates_t *amdp, *nextp;
195 for(amdp = amandates_list; amdp != NULL; amdp = nextp) {
200 amandates_list = NULL;
208 amandates_t *prevp, *amdp;
211 (void)import; /* Quiet unused parameter warning */
215 amdp = amandates_list;
216 while (amdp != NULL) {
217 if ((rc = strcmp(name, amdp->name)) <= 0)
222 if (!(amdp && (rc == 0))) {
223 amandates_t *newp = alloc(SIZEOF(amandates_t));
224 newp->name = stralloc(name);
225 for (level = 0; level < DUMP_LEVELS; level++)
226 newp->dates[level] = EPOCH;
229 #ifndef __lint /* Remove complaint about NULL pointer assignment */
235 amandates_list = newp;
237 import_dumpdates(newp);
247 return lookup(name, 1);
259 amdp = lookup(name, 0);
261 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
262 qname = quote_string(name);
263 /* this is not allowed, but we can ignore it */
264 dbprintf(_("amandates botch: %s lev %d: new dumpdate %ld old %ld\n"),
265 qname, level, (long) dumpdate, (long) amdp->dates[level]);
270 amdp->dates[level] = dumpdate;
285 amdp = lookup(name, 1);
287 if(level < 0 || level >= DUMP_LEVELS || dumpdate < amdp->dates[level]) {
288 /* this is not allowed, but we can ignore it */
289 qname = quote_string(name);
290 dbprintf(_("amandates updateone: %s lev %d: new dumpdate %ld old %ld"),
291 name, level, (long) dumpdate, (long) amdp->dates[level]);
296 amdp->dates[level] = dumpdate;
301 /* -------------------------- */
316 devname = amname_to_devname(amdp->name);
318 if((dumpdf = fopen("/etc/dumpdates", "r")) == NULL) {
323 for(; (line = agets(dumpdf)) != NULL; free(line)) {
329 skip_whitespace(s, ch);
331 continue; /* no fname field */
334 skip_non_whitespace(s, ch);
335 s[-1] = '\0'; /* terminate fname */
337 skip_whitespace(s, ch);
338 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
339 continue; /* no level field */
343 skip_whitespace(s, ch);
345 continue; /* no dumpdate field */
347 dumpdate = unctime(s-1);
349 if(strcmp(fname, devname) != 0 || level < 0 || level >= DUMP_LEVELS) {
353 if(dumpdate != -1 && dumpdate > amdp->dates[level]) {
354 if(!readonly) updated = 1;
355 amdp->dates[level] = dumpdate;