Imported Upstream version 3.3.0
[debian/amanda] / server-src / tapefile.c
index 6d2b86453cf9667fd21e126deb50436256bf9f72..b4212e5894238b47bc4d49e9801938ba26f4d78e 100644 (file)
  * 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);
 
@@ -70,8 +82,9 @@ char *tapefile;
     return 0;
 }
 
-int write_tapelist(tapefile)
-char *tapefile;
+int
+write_tapelist(
+    char *tapefile)
 {
     tape_t *tp;
     FILE *tapef;
@@ -86,14 +99,21 @@ char *tapefile;
     }
 
     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);
@@ -102,20 +122,23 @@ char *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;
 
@@ -127,8 +150,9 @@ char *label;
 
 
 
-tape_t *lookup_tapepos(pos)
-int pos;
+tape_t *
+lookup_tapepos(
+    int pos)
 {
     tape_t *tp;
 
@@ -139,18 +163,20 @@ int pos;
 }
 
 
-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;
@@ -161,8 +187,18 @@ int lookup_nb_tape()
     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;
@@ -176,12 +212,12 @@ tape_t *lookup_last_reusable_tape(skip)
      * 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];
@@ -197,14 +233,15 @@ tape_t *lookup_last_reusable_tape(skip)
     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;
@@ -212,8 +249,9 @@ int reusable_tape(tp)
     return (count >= getconf_int(CNF_TAPECYCLE));
 }
 
-void remove_tapelabel(label)
-char *label;
+void
+remove_tapelabel(
+    char *label)
 {
     tape_t *tp, *prev, *next;
 
@@ -221,35 +259,41 @@ char *label;
     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;
@@ -266,7 +310,8 @@ char *label;
     return new;
 }
 
-int guess_runs_from_tapelist()
+int
+guess_runs_from_tapelist(void)
 {
     tape_t *tp;
     int i, ntapes, tape_ndays, dumpcycle, runtapes, runs;
@@ -283,7 +328,7 @@ int guess_runs_from_tapelist()
        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;
@@ -305,16 +350,17 @@ int guess_runs_from_tapelist()
     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;
@@ -327,74 +373,192 @@ char *line;
        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);
+    }
 }