/*
 * 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: disk_history.c,v 1.13 2006/05/25 01:47:19 johnfranks Exp $
 *
 * functions for obtaining backup history
 */

#include "amanda.h"
#include "disk_history.h"

static DUMP_ITEM *disk_hist = NULL;

void
clear_list(void)
{
    DUMP_ITEM *item, *this;

    item = disk_hist;
    while (item != NULL)
    {
	this = item;
	item = item->next;
	amfree(this->hostname);
	while(this->tapes != NULL) {
	    tapelist_t *tapes = this->tapes;
	    this->tapes = tapes->next;
	    amfree(tapes->label);
	    amfree(tapes->files);
	    amfree(tapes);
	}
	amfree(this);
    }
    disk_hist = NULL;
}

/* add item, maintain list ordered by oldest date last */

void
add_dump(
    char *      hostname,
    char *	date,
    int		level,
    char *	storage,
    char *	tape,
    off_t	file,
    int		partnum,
    int		maxpart)
{
    DUMP_ITEM *new, *item, *before;
    int isafile = 0;

    if(tape[0] == '/')
	isafile = 1; /* XXX kludgey, like this whole thing */

    /* See if we already have partnum=partnum-1 */
    if (partnum > 1) {
	for(item = disk_hist, before = NULL; item;
	    before = item, item = item->next) {
	    if (g_str_equal(item->date, date) &&
		item->level == level && item->is_split &&
		g_str_equal(item->storage, storage)) {
		item->tapes = append_to_tapelist(item->tapes, storage, tape, file,
						 partnum, isafile);
		if (maxpart > item->maxpart)
		    item->maxpart = maxpart;
		return;
	    }
	}
	return;
    }

    new = (DUMP_ITEM *)g_malloc(sizeof(DUMP_ITEM));
    strncpy(new->date, date, sizeof(new->date)-1);
    new->date[sizeof(new->date)-1] = '\0';
    new->level = level;
    strncpy(new->storage, storage, sizeof(new->storage)-1);
    new->storage[sizeof(new->storage)-1] = '\0';
    strncpy(new->tape, tape, sizeof(new->tape)-1);
    new->tape[sizeof(new->tape)-1] = '\0';
    new->file = file;
    new->maxpart = maxpart;
    if(partnum == -1)
        new->is_split = 0;
    else
        new->is_split = 1;
    new->tapes = NULL;
    new->hostname = g_strdup(hostname);

    new->tapes = append_to_tapelist(new->tapes, storage, tape, file, partnum, isafile);

    if (disk_hist == NULL)
    {
	disk_hist = new;
	new->next = NULL;
	return;
    }

    /* prepend this item to the history list, if it's newer */
    /* XXX this should probably handle them being on the same date with
       datestamp_uax or something */
    if (strcmp(disk_hist->date, new->date) < 0)
    {
	new->next = disk_hist;
	disk_hist = new;
	return;
    }

    /* append this item to the history list, if it's older */
    before = disk_hist;
    item = disk_hist->next;
    while ((item != NULL) && (strcmp(item->date, new->date) >= 0))
    {
	before = item;
	item = item->next;
    }
    new->next = item;
    before->next = new;
}

void
clean_dump(void)
{
    DUMP_ITEM *item, *before;

    /* check if the maxpart part is avaliable */
    for(item = disk_hist, before = NULL; item;
					 before = item, item = item->next) {
	int found_maxpart = 0;
	tapelist_t *cur_tape;

	if (item->maxpart > 1) {
	    for (cur_tape = item->tapes; cur_tape; cur_tape = cur_tape->next) {
		int files;
		for(files=0; files<cur_tape->numfiles; files++) {
		    if (cur_tape->partnum[files] == item->maxpart) {
			found_maxpart = 1;
		    }
		}
	    }
	    if (found_maxpart == 0) {
		DUMP_ITEM *myitem = item;

		if (before)
		    before->next = item->next;
		else
		    disk_hist = item->next;
		item = item->next;
		/* free myitem */
		free_tapelist(myitem->tapes);
		amfree(myitem->hostname);
		amfree(myitem);
		if (item == NULL)
		    break;
	    }
	}
    }
}

DUMP_ITEM *
first_dump(void)
{
    return disk_hist;
}
