Repository URL to install this package:
|
Version:
3.4.5-5.el7 ▾
|
/*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1998 University of Maryland at College Park
* Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
* Copyright (c) 2013-2016 Carbonite, Inc. All Rights Reserved.
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Authors: the Amanda Development Team. Its members are listed in a
* file named AUTHORS, in the root directory of this distribution.
*/
/*
* $Id: amandates.c,v 1.21 2006/07/25 18:35:21 martinea Exp $
*
* manage amandates file, that mimics /etc/dumpdates, but stores
* GNUTAR dates
*/
#include "amanda.h"
#include "getfsent.h"
#include "amutil.h"
#include "amandates.h"
static amandates_t *amandates_list = NULL;
static FILE *amdf = NULL;
static int updated, readonly;
static char *g_amandates_file = NULL;
static void import_dumpdates(amandates_t *);
static void enter_record(char *, int , time_t);
static amandates_t *lookup(char *name, int import);
int
start_amandates(
char *amandates_file,
int open_readwrite)
{
int rc, level = 0;
long ldate = 0L;
char *line;
char *name;
char *s;
int ch;
char *qname;
if (amandates_file == NULL) {
errno = 0;
return 0;
}
/* clean up from previous invocation */
if(amdf != NULL)
finish_amandates();
if(amandates_list != NULL)
free_amandates();
amfree(g_amandates_file);
/* initialize state */
updated = 0;
readonly = !open_readwrite;
amdf = NULL;
amandates_list = NULL;
g_amandates_file = g_strdup(amandates_file);
/* open the file */
// if (access(amandates_file,F_OK))
// /* not yet existing */
// if ( (rc = open(amandates_file,(O_CREAT|O_RDWR),0644)) != -1 )
// /* open/create successfull */
// aclose(rc);
if (open_readwrite)
amdf = fopen(amandates_file, "r+");
else
amdf = fopen(amandates_file, "r");
/* create it if we need to */
if (amdf == NULL) {
if (errno == ENOENT) {
amdf = fopen(amandates_file, "w+");
}
}
if (amdf == NULL) {
// errno is set
return 0;
}
if(open_readwrite)
rc = amflock(fileno(amdf), amandates_file);
else
rc = amroflock(fileno(amdf), amandates_file);
if(rc == -1) {
error(_("could not lock %s: %s"), amandates_file, strerror(errno));
/*NOTREACHED*/
}
for(; (line = agets(amdf)) != NULL; free(line)) {
if (line[0] == '\0')
continue;
s = line;
ch = *s++;
skip_whitespace(s, ch);
if(ch == '\0') {
continue; /* no name field */
}
qname = s - 1;
skip_quoted_string(s, ch);
s[-1] = '\0'; /* terminate the name */
name = unquote_string(qname);
skip_whitespace(s, ch);
if(ch == '\0' || sscanf(s - 1, "%d %ld", &level, &ldate) != 2) {
amfree(name);
continue; /* no more fields */
}
if(level < 0 || level >= DUMP_LEVELS) {
amfree(name);
continue;
}
enter_record(name, level, (time_t) ldate);
amfree(name);
}
if(ferror(amdf)) {
error(_("reading %s: %s"), amandates_file, strerror(errno));
/*NOTREACHED*/
}
updated = 0; /* reset updated flag */
return 1;
}
void
finish_amandates(void)
{
amandates_t *amdp;
int level;
char *qname;
if(amdf == NULL)
return;
if(updated) {
if(readonly) {
error(_("updated amandates after opening readonly"));
/*NOTREACHED*/
}
rewind(amdf);
for(amdp = amandates_list; amdp != NULL; amdp = amdp->next) {
for(level = 0; level < DUMP_LEVELS; level++) {
if(amdp->dates[level] == EPOCH) continue;
qname = quote_string(amdp->name);
g_fprintf(amdf, "%s %d %ld\n",
qname, level, (long) amdp->dates[level]);
amfree(qname);
}
}
}
if(amfunlock(fileno(amdf), g_amandates_file) == -1) {
error(_("could not unlock %s: %s"), g_amandates_file, strerror(errno));
/*NOTREACHED*/
}
if (fclose(amdf) == EOF) {
error(_("error [closing %s: %s]"), g_amandates_file, strerror(errno));
/*NOTREACHED*/
}
amdf = NULL;
}
void
free_amandates(void)
{
amandates_t *amdp, *nextp;
for(amdp = amandates_list; amdp != NULL; amdp = nextp) {
nextp = amdp->next;
amfree(amdp->name);
amfree(amdp);
}
amandates_list = NULL;
}
static amandates_t *
lookup(
char * name,
int import)
{
amandates_t *prevp, *amdp;
int rc, level;
(void)import; /* Quiet unused parameter warning */
rc = 0;
prevp = NULL;
amdp = amandates_list;
while (amdp != NULL) {
if ((rc = strcmp(name, amdp->name)) <= 0)
break;
prevp = amdp;
amdp = amdp->next;
}
if (!(amdp && (rc == 0))) {
amandates_t *newp = g_malloc(sizeof(amandates_t));
newp->name = g_strdup(name);
for (level = 0; level < DUMP_LEVELS; level++)
newp->dates[level] = EPOCH;
newp->next = amdp;
if (prevp != NULL) {
#ifndef __lint /* Remove complaint about NULL pointer assignment */
prevp->next = newp;
#else
(void)prevp;
#endif
} else {
amandates_list = newp;
}
import_dumpdates(newp);
return newp;
}
return amdp;
}
amandates_t *
amandates_lookup(
char * name)
{
return lookup(name, 1);
}
static void
enter_record(
char * name,
int level,
time_t dumpdate)
{
amandates_t *amdp;
char *qname;
amdp = lookup(name, 0);
if (level < 0 || level >= DUMP_LEVELS) {
qname = quote_string(name);
/* this is not allowed, but we can ignore it */
dbprintf(_("amandates botch: %s lev %d: new dumpdate %ld\n"),
qname, level, (long) dumpdate);
amfree(qname);
return;
} else if(dumpdate < amdp->dates[level]) {
qname = quote_string(name);
/* this is not allowed, but we can ignore it */
dbprintf(_("amandates botch: %s lev %d: new dumpdate %ld old %ld\n"),
qname, level, (long) dumpdate, (long) amdp->dates[level]);
amfree(qname);
return;
}
amdp->dates[level] = dumpdate;
}
void
amandates_updateone(
char * name,
int level,
time_t dumpdate)
{
amandates_t *amdp;
char *qname;
assert(!readonly);
amdp = lookup(name, 1);
if (level < 0 || level >= DUMP_LEVELS) {
/* this is not allowed, but we can ignore it */
qname = quote_string(name);
dbprintf(_("amandates updateone: %s lev %d: bad level, dumpdate %ld"),
name, level, (long) dumpdate);
amfree(qname);
return;
} else if (dumpdate < amdp->dates[level]) {
/* this is not allowed, but we can ignore it */
qname = quote_string(name);
dbprintf(_("amandates updateone: %s lev %d: new dumpdate %ld old %ld"),
name, level, (long) dumpdate, (long) amdp->dates[level]);
amfree(qname);
return;
}
amdp->dates[level] = dumpdate;
updated = 1;
}
/* -------------------------- */
static void
import_dumpdates(
amandates_t * amdp)
{
char *devname;
char *line;
char *fname;
int level = 0;
time_t dumpdate;
FILE *dumpdf;
char *s;
int ch;
devname = amname_to_devname(amdp->name);
if((dumpdf = fopen("/etc/dumpdates", "r")) == NULL) {
amfree(devname);
return;
}
for(; (line = agets(dumpdf)) != NULL; free(line)) {
if (line[0] == '\0')
continue;
s = line;
ch = *s++;
skip_whitespace(s, ch);
if(ch == '\0') {
continue; /* no fname field */
}
fname = s - 1;
skip_non_whitespace(s, ch);
s[-1] = '\0'; /* terminate fname */
skip_whitespace(s, ch);
if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
continue; /* no level field */
}
skip_integer(s, ch);
skip_whitespace(s, ch);
if(ch == '\0') {
continue; /* no dumpdate field */
}
dumpdate = unctime(s-1);
if(!g_str_equal(fname, devname) || level < 0 || level >= DUMP_LEVELS) {
continue;
}
if(dumpdate != -1 && dumpdate > amdp->dates[level]) {
if(!readonly) updated = 1;
amdp->dates[level] = dumpdate;
}
}
afclose(dumpdf);
amfree(devname);
}