* file named AUTHORS, in the root directory of this distribution.
*/
/*
- * $Id: tapefile.c,v 1.15.2.6.6.7 2003/10/24 13:44:49 martinea Exp $
+ * $Id: tapefile.c,v 1.37 2006/07/21 00:25:52 martinea Exp $
*
* routines to read and write the amanda active tape list
*/
#include "amanda.h"
+#include "match.h"
#include "tapefile.h"
#include "conffile.h"
static tape_t *tape_list = NULL;
/* local functions */
-static tape_t *parse_tapeline P((int *status, char *line));
-static tape_t *insert P((tape_t *list, tape_t *tp));
-static time_t stamp2time P((int datestamp));
+static tape_t *parse_tapeline(int *status, char *line);
+static tape_t *insert(tape_t *list, tape_t *tp);
+static time_t stamp2time(char *datestamp);
-
-
-int read_tapelist(tapefile)
-char *tapefile;
+int
+read_tapelist(
+ char *tapefile)
{
tape_t *tp;
FILE *tapef;
int pos;
char *line = NULL;
- int status;
+ int status = 0;
tape_list = NULL;
if((tapef = fopen(tapefile,"r")) == NULL) {
- return 1;
+ if (errno == ENOENT) {
+ /* no tapelist is equivalent to an empty tapelist */
+ return 0;
+ } else {
+ g_debug("Error opening '%s': %s", tapefile, strerror(errno));
+ return 1;
+ }
}
while((line = agets(tapef)) != NULL) {
+ if (line[0] == '\0') {
+ amfree(line);
+ continue;
+ }
tp = parse_tapeline(&status, line);
amfree(line);
- if(tp == NULL && status != 0) return 1;
- if(tp != NULL) tape_list = insert(tape_list, tp);
+ if(tp == NULL && status != 0)
+ return 1;
+ if(tp != NULL)
+ tape_list = insert(tape_list, tp);
}
afclose(tapef);
return 0;
}
-int write_tapelist(tapefile)
-char *tapefile;
+int
+write_tapelist(
+ char *tapefile)
{
tape_t *tp;
FILE *tapef;
}
for(tp = tape_list; tp != NULL; tp = tp->next) {
- fprintf(tapef, "%d %s", tp->datestamp, tp->label);
- if(tp->reuse) fprintf(tapef, " reuse");
- else fprintf(tapef, " no-reuse");
- fprintf(tapef, "\n");
+ g_fprintf(tapef, "%s %s", tp->datestamp, tp->label);
+ if(tp->reuse) g_fprintf(tapef, " reuse");
+ else g_fprintf(tapef, " no-reuse");
+ if (tp->barcode)
+ g_fprintf(tapef, " BARCODE:%s", tp->barcode);
+ if (tp->meta)
+ g_fprintf(tapef, " META:%s", tp->meta);
+ if (tp->comment)
+ g_fprintf(tapef, " #%s", tp->comment);
+ g_fprintf(tapef, "\n");
}
if (fclose(tapef) == EOF) {
- fprintf(stderr,"error [closing %s: %s]", newtapefile, strerror(errno));
+ g_fprintf(stderr,_("error [closing %s: %s]"), newtapefile, strerror(errno));
+ amfree(newtapefile);
return 1;
}
rc = rename(newtapefile, tapefile);
return(rc != 0);
}
-void clear_tapelist()
+void
+clear_tapelist(void)
{
tape_t *tp, *next;
for(tp = tape_list; tp; tp = next) {
amfree(tp->label);
+ amfree(tp->datestamp);
next = tp->next;
amfree(tp);
}
tape_list = NULL;
}
-tape_t *lookup_tapelabel(label)
-char *label;
+tape_t *
+lookup_tapelabel(
+ const char *label)
{
tape_t *tp;
-tape_t *lookup_tapepos(pos)
-int pos;
+tape_t *
+lookup_tapepos(
+ int pos)
{
tape_t *tp;
}
-tape_t *lookup_tapedate(datestamp)
-int datestamp;
+tape_t *
+lookup_tapedate(
+ char *datestamp)
{
tape_t *tp;
for(tp = tape_list; tp != NULL; tp = tp->next) {
- if(tp->datestamp == datestamp) return tp;
+ if(strcmp(tp->datestamp, datestamp) == 0) return tp;
}
return NULL;
}
-int lookup_nb_tape()
+int
+lookup_nb_tape(void)
{
tape_t *tp;
int pos=0;
return pos;
}
-tape_t *lookup_last_reusable_tape(skip)
- int skip;
+
+char *
+get_last_reusable_tape_label(
+ int skip)
+{
+ tape_t *tp = lookup_last_reusable_tape(skip);
+ return (tp != NULL) ? tp->label : NULL;
+}
+
+tape_t *
+lookup_last_reusable_tape(
+ int skip)
{
tape_t *tp, **tpsave;
int count=0;
* caller. If skip is zero, the oldest is returned, if it is
* one, the next oldest, two, the next to next oldest and so on.
*/
- tpsave = alloc((skip + 1) * sizeof (*tpsave));
+ tpsave = alloc((skip + 1) * SIZEOF(*tpsave));
for(s = 0; s <= skip; s++) {
tpsave[s] = NULL;
}
for(tp = tape_list; tp != NULL; tp = tp->next) {
- if(tp->reuse == 1 && tp->datestamp > 0 && match (labelstr, tp->label)) {
+ if(tp->reuse == 1 && strcmp(tp->datestamp,"0") != 0 && match (labelstr, tp->label)) {
count++;
for(s = skip; s > 0; s--) {
tpsave[s] = tpsave[s - 1];
return tp;
}
-int reusable_tape(tp)
- tape_t *tp;
+int
+reusable_tape(
+ tape_t *tp)
{
int count = 0;
if(tp == NULL) return 0;
if(tp->reuse == 0) return 0;
- if(tp->datestamp == 0) return 1;
+ if( strcmp(tp->datestamp,"0") == 0) return 1;
while(tp != NULL) {
if(tp->reuse == 1) count++;
tp = tp->prev;
return (count >= getconf_int(CNF_TAPECYCLE));
}
-void remove_tapelabel(label)
-char *label;
+void
+remove_tapelabel(
+ char *label)
{
tape_t *tp, *prev, *next;
if(tp != NULL) {
prev = tp->prev;
next = tp->next;
+ /*@ignore@*/
if(prev != NULL)
prev->next = next;
else /* begin of list */
tape_list = next;
if(next != NULL)
next->prev = prev;
+ /*@end@*/
while (next != NULL) {
next->position--;
next = next->next;
}
+ amfree(tp->datestamp);
amfree(tp->label);
amfree(tp);
}
}
-tape_t *add_tapelabel(datestamp, label)
-int datestamp;
-char *label;
+tape_t *
+add_tapelabel(
+ char *datestamp,
+ char *label,
+ char *comment)
{
tape_t *cur, *new;
/* insert a new record to the front of the list */
- new = (tape_t *) alloc(sizeof(tape_t));
+ new = (tape_t *) alloc(SIZEOF(tape_t));
- new->datestamp = datestamp;
+ new->datestamp = stralloc(datestamp);
new->position = 0;
new->reuse = 1;
new->label = stralloc(label);
+ new->comment = comment? stralloc(comment) : NULL;
new->prev = NULL;
if(tape_list != NULL) tape_list->prev = new;
return new;
}
-int guess_runs_from_tapelist()
+int
+guess_runs_from_tapelist(void)
{
tape_t *tp;
int i, ntapes, tape_ndays, dumpcycle, runtapes, runs;
if((tp = lookup_tapepos(i)) == NULL) break;
tape_time = stamp2time(tp->datestamp);
- tape_ndays = days_diff(tape_time, today);
+ tape_ndays = (int)days_diff(tape_time, today);
if(tape_ndays < dumpcycle) ntapes++;
else break;
return runs;
}
-static tape_t *parse_tapeline(status, line)
-int *status;
-char *line;
+static tape_t *
+parse_tapeline(
+ int *status,
+ char *line)
{
tape_t *tp = NULL;
char *s, *s1;
int ch;
*status = 0;
- tp = (tape_t *) alloc(sizeof(tape_t));
+ tp = (tape_t *) alloc(SIZEOF(tape_t));
tp->prev = NULL;
tp->next = NULL;
amfree(tp);
return NULL;
}
- if (sscanf(s - 1, "%d", &tp->datestamp) != 1) {
- amfree(tp);
- *status = 1;
- return NULL;
- }
- skip_integer(s, ch);
+ s1 = s - 1;
+ skip_non_whitespace(s, ch);
+ s[-1] = '\0';
+ tp->datestamp = stralloc(s1);
skip_whitespace(s, ch);
s1 = s - 1;
skip_non_whitespace(s, ch);
s[-1] = '\0';
tp->label = stralloc(s1);
+
skip_whitespace(s, ch);
tp->reuse = 1;
-#define sc "reuse"
- if(strncmp(s - 1, sc, sizeof(sc)-1) == 0)
+ if(strncmp_const(s - 1, "reuse") == 0) {
tp->reuse = 1;
-#undef sc
-#define sc "no-reuse"
- if(strncmp(s - 1, sc, sizeof(sc)-1) == 0)
+ s1 = s - 1;
+ skip_non_whitespace(s, ch);
+ s[-1] = '\0';
+ skip_whitespace(s, ch);
+ }
+ if(strncmp_const(s - 1, "no-reuse") == 0) {
tp->reuse = 0;
-#undef sc
+ s1 = s - 1;
+ skip_non_whitespace(s, ch);
+ s[-1] = '\0';
+ skip_whitespace(s, ch);
+ }
+
+ if (strncmp_const(s - 1, "BARCODE:") == 0) {
+ s1 = s - 1 + 8;
+ skip_non_whitespace(s, ch);
+ s[-1] = '\0';
+ skip_whitespace(s, ch);
+ tp->barcode = stralloc(s1);
+ } else {
+ tp->barcode = NULL;
+ }
+
+ if (strncmp_const(s - 1, "META:") == 0) {
+ s1 = s - 1 + 5;
+ skip_non_whitespace(s, ch);
+ s[-1] = '\0';
+ skip_whitespace(s, ch);
+ tp->meta = stralloc(s1);
+ } else {
+ tp->meta = NULL;
+ }
+
+ if (*(s - 1) == '#') {
+ tp->comment = stralloc(s); /* skip leading '#' */
+ } else {
+ tp->comment = NULL;
+ }
return tp;
}
/* insert in reversed datestamp order */
-static tape_t *insert(list, tp)
-tape_t *list, *tp;
+/*@ignore@*/
+static tape_t *
+insert(
+ tape_t *list,
+ tape_t *tp)
{
tape_t *prev, *cur;
prev = NULL;
cur = list;
- while(cur != NULL && cur->datestamp >= tp->datestamp) {
+ while(cur != NULL && strcmp(cur->datestamp, tp->datestamp) >= 0) {
prev = cur;
cur = cur->next;
}
tp->prev = prev;
tp->next = cur;
- if(prev == NULL) list = tp;
- else prev->next = tp;
- if(cur !=NULL) cur->prev = tp;
+ if(prev == NULL) {
+ list = tp;
+#ifndef __lint
+ } else {
+ prev->next = tp;
+#endif
+ }
+ if(cur !=NULL)
+ cur->prev = tp;
return list;
}
+/*@end@*/
-
-static time_t stamp2time(datestamp)
-int datestamp;
/*
- * Converts datestamp (an int of the form YYYYMMDD) into a real time_t value.
+ * Converts datestamp (an char of the form YYYYMMDD or YYYYMMDDHHMMSS) into a real
+ * time_t value.
* Since the datestamp contains no timezone or hh/mm/ss information, the
* value is approximate. This is ok for our purposes, since we round off
* scheduling calculations to the nearest day.
*/
+
+static time_t
+stamp2time(
+ char *datestamp)
{
- struct tm tm;
+ struct tm *tm;
time_t now;
+ char date[9];
+ int dateint;
+ strncpy(date, datestamp, 8);
+ date[8] = '\0';
+ dateint = atoi(date);
now = time(0);
- tm = *localtime(&now); /* initialize sec/min/hour & gmtoff */
+ tm = localtime(&now); /* initialize sec/min/hour & gmtoff */
+
+ if (!tm) {
+ tm = alloc(SIZEOF(struct tm));
+ tm->tm_sec = 0;
+ tm->tm_min = 0;
+ tm->tm_hour = 0;
+ tm->tm_wday = 0;
+ tm->tm_yday = 0;
+ tm->tm_isdst = 0;
+ }
+
+
+ tm->tm_year = ( dateint / 10000) - 1900;
+ tm->tm_mon = ((dateint % 10000) / 100) - 1;
+ tm->tm_mday = ((dateint % 100) );
+
+ return mktime(tm);
+}
- tm.tm_year = ( datestamp / 10000) - 1900;
- tm.tm_mon = ((datestamp % 10000) / 100) - 1;
- tm.tm_mday = ((datestamp % 100) );
+char *
+list_new_tapes(
+ int nb)
+{
+ tape_t *lasttp, *iter;
+ char *result = NULL;
+
+ /* Find latest reusable new tape */
+ lasttp = lookup_tapepos(lookup_nb_tape());
+ while (lasttp && lasttp->reuse == 0)
+ lasttp = lasttp->prev;
+
+ if(lasttp && nb > 0 && strcmp(lasttp->datestamp,"0") == 0) {
+ int c = 0;
+ iter = lasttp;
+ /* count the number of tapes we *actually* used */
+ while(iter && nb > 0 && strcmp(iter->datestamp,"0") == 0) {
+ if (iter->reuse) {
+ c++;
+ nb--;
+ }
+ iter = iter->prev;
+ }
- return mktime(&tm);
+ if(c == 1) {
+ result = g_strdup_printf(
+ _("The next new tape already labelled is: %s."),
+ lasttp->label);
+ } else {
+ result = g_strdup_printf(
+ _("The next %d new tapes already labelled are: %s"),
+ c, lasttp->label);
+ iter = lasttp->prev;
+ c--;
+ while(iter && c > 0 && strcmp(iter->datestamp,"0") == 0) {
+ if (iter->reuse) {
+ result = vstrextend(&result, ", ", iter->label, NULL);
+ c--;
+ }
+ iter = iter->prev;
+ }
+ }
+ }
+ return result;
+}
+
+void
+print_new_tapes(
+ FILE *output,
+ int nb)
+{
+ char *result = list_new_tapes(nb);
+
+ if (result) {
+ g_fprintf(output,"%s\n", result);
+ amfree(result);
+ }
}