lintian doesn't like orphan packages with uploaders...
[debian/amanda] / server-src / diskfile.c
index e11ffd83e851025750b6e47c3c8aaf16fdba2171..d8e11dce165c1669eb061945be621eda64deb5e6 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * 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.
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -89,6 +90,12 @@ end:
     return config_errors(NULL);
 }
 
+am_host_t *
+get_hostlist(void)
+{
+    return hostlist;
+}
+
 am_host_t *
 lookup_host(
     const char *hostname)
@@ -198,6 +205,9 @@ add_disk(
     disk = alloc(SIZEOF(disk_t));
     bzero(disk, SIZEOF(disk_t));
     disk->line = 0;
+    disk->allow_split = 0;
+    disk->max_warnings = 20;
+    disk->splitsize = (off_t)0;
     disk->tape_splitsize = (off_t)0;
     disk->split_diskbuffer = NULL;
     disk->fallback_splitsize = (off_t)0;
@@ -333,6 +343,7 @@ free_disklist(
 
     while (dl->head != NULL) {
        dp = dequeue_disk(dl);
+       amfree(dp->filename);
        amfree(dp->name);
        amfree(dp->hostname);
        amfree(dp->device);
@@ -415,6 +426,28 @@ parse_diskline(
     fp = s - 1;
     skip_non_whitespace(s, ch);
     s[-1] = '\0';
+    if (g_str_equal(fp, "includefile")) {
+       char *include_name;
+       char *include_filename;
+       skip_whitespace(s, ch);
+       if (ch == '\0' || ch == '#') {
+           disk_parserror(filename, line_num, _("include filename name expected"));
+           return (-1);
+       }
+       fp = s - 1;
+       skip_quoted_string(s, ch);
+       s[-1] = '\0';
+       include_name = unquote_string(fp);
+       include_filename = config_dir_relative(include_name);
+       read_diskfile(include_filename, lst);
+       g_free(include_filename);
+       g_free(include_name);
+       if (config_errors(NULL) >= CFGERR_WARNINGS) {
+           return -1;
+       } else {
+           return 0;
+       }
+    }
     host = lookup_host(fp);
     if (host == NULL) {
        hostname = stralloc(fp);
@@ -481,7 +514,7 @@ parse_diskline(
            amfree(hostname);
            return (-1);
        }
-       if ((dtype = lookup_dumptype(dumptype)) == NULL) {
+       if (lookup_dumptype(dumptype) == NULL) {
            diskdevice = dumptype;
            skip_whitespace(s, ch);
            if(ch == '\0' || ch == '#') {
@@ -532,6 +565,7 @@ parse_diskline(
     }
     if (!disk) {
        disk = alloc(SIZEOF(disk_t));
+       disk->filename = g_strdup(filename);
        disk->line = line_num;
        disk->hostname = hostname;
        disk->name = diskname;
@@ -641,6 +675,7 @@ parse_diskline(
     }
 
     disk->dtype_name        = dumptype_name(dtype);
+    disk->config            = dtype;
     disk->program           = dumptype_get_program(dtype);
     disk->exclude_list     = duplicate_sl(dumptype_get_exclude(dtype).sl_list);
     disk->exclude_file     = duplicate_sl(dumptype_get_exclude(dtype).sl_file);
@@ -653,9 +688,17 @@ parse_diskline(
 /*    disk->frequency       = dumptype_get_frequency(dtype);*/
     disk->auth               = dumptype_get_auth(dtype);
     disk->maxdumps          = dumptype_get_maxdumps(dtype);
+    disk->allow_split        = dumptype_get_allow_split(dtype);
+    disk->max_warnings       = dumptype_get_max_warnings(dtype);
     disk->tape_splitsize     = dumptype_get_tape_splitsize(dtype);
     disk->split_diskbuffer   = dumptype_get_split_diskbuffer(dtype);
     disk->fallback_splitsize = dumptype_get_fallback_splitsize(dtype);
+    if (disk->allow_split) {
+       tapetype_t *tapetype = lookup_tapetype(getconf_str(CNF_TAPETYPE));
+       disk->splitsize = tapetype_get_part_size(tapetype);
+    } else {
+       disk->splitsize = disk->tape_splitsize;
+    }
     disk->maxpromoteday             = dumptype_get_maxpromoteday(dtype);
     disk->bumppercent       = dumptype_get_bumppercent(dtype);
     disk->bumpsize          = dumptype_get_bumpsize(dtype);
@@ -693,6 +736,7 @@ parse_diskline(
     disk->comprate[0]       = dumptype_get_comprate(dtype)[0];
     disk->comprate[1]       = dumptype_get_comprate(dtype)[1];
     disk->data_path         = dumptype_get_data_path(dtype);
+    disk->dump_limit        = dumptype_get_dump_limit(dtype);
 
     /*
      * Boolean parameters with no value (Appears here as value 2) defaults
@@ -1210,19 +1254,57 @@ optionstr(
     return result;
 }
 
+typedef struct {
+    am_feature_t  *features;
+    char          *result;
+} xml_app_t;
+
+/* A GHFunc (callback for g_hash_table_foreach) */
+static void xml_property(
+    gpointer key_p,
+    gpointer value_p,
+    gpointer user_data_p)
+{
+    char       *tmp;
+    property_t *property = value_p;
+    xml_app_t  *xml_app = user_data_p;
+    GSList     *value;
+    GString    *strbuf;
+
+    strbuf = g_string_new(xml_app->result);
+
+    tmp = amxml_format_tag("name", (char *)key_p);
+    g_string_append_printf(strbuf, "    <property>\n      %s\n", tmp);
+    g_free(tmp);
+
+    // TODO if client have fe_xml_property_priority
+    if (property->priority
+       && am_has_feature(xml_app->features, fe_xml_property_priority))
+       g_string_append(strbuf, "      <priority>yes</priority>\n");
+
+    for (value = property->values; value != NULL; value = value->next) {
+       tmp = amxml_format_tag("value", value->data);
+       g_string_append_printf(strbuf, "      %s", tmp);
+       g_free(tmp);
+    }
+    g_string_append_printf(strbuf, "\n    </property>\n");
+
+    g_free(xml_app->result);
+    xml_app->result = g_string_free(strbuf, FALSE);
+}
+
 char *
 xml_optionstr(
     disk_t *           dp,
     int                 to_server)
 {
-    char *auth_opt = stralloc("");
-    char *kencrypt_opt = stralloc("");
-    char *compress_opt = stralloc("");
+    char *auth_opt;
+    char *kencrypt_opt;
+    char *compress_opt;
     char *encrypt_opt = stralloc("");
     char *decrypt_opt = stralloc("");
-    char *record_opt = stralloc("");
-    char *index_opt = stralloc("");
+    char *record_opt;
+    char *index_opt;
     char *data_path_opt = stralloc("");
     char *exclude = stralloc("");
     char *exclude_file = NULL;
@@ -1246,14 +1328,16 @@ xml_optionstr(
     qdpname = quote_string(dp->name);
     if (am_has_feature(their_features, fe_options_auth)) {
        auth_opt = vstralloc("  <auth>", dp->auth, "</auth>\n", NULL);
+    } else {
+       auth_opt = stralloc("");
     }
 
     switch(dp->compress) {
     case COMP_FAST:
-       compress_opt = "  <compress>FAST</compress>\n";
+       compress_opt = stralloc("  <compress>FAST</compress>\n");
        break;
     case COMP_BEST:
-       compress_opt = "  <compress>BEST</compress>\n";
+       compress_opt = stralloc("  <compress>BEST</compress>\n");
        break;
     case COMP_CUST:
        compress_opt = vstralloc("  <compress>CUSTOM"
@@ -1263,19 +1347,20 @@ xml_optionstr(
                                 "  </compress>\n", NULL);
        break;
     case COMP_SERVER_FAST:
-       compress_opt = "  <compress>SERVER-FAST</compress>\n";
+       compress_opt = stralloc("  <compress>SERVER-FAST</compress>\n");
        break;
     case COMP_SERVER_BEST:
-       compress_opt = "  <compress>SERVER-BEST</compress>\n";
+       compress_opt = stralloc("  <compress>SERVER-BEST</compress>\n");
        break;
     case COMP_SERVER_CUST:
-       compress_opt = "  <compress>SERVER-CUSTOM</compress>\n";
        compress_opt = vstralloc("  <compress>SERVER-CUSTOM"
                                 "<custom-compress-program>",
                                 dp->srvcompprog,
                                 "</custom-compress-program>\n"
                                 "  </compress>\n", NULL);
        break;
+    default:
+       compress_opt = stralloc("");
     }
 
     switch(dp->encrypt) {
@@ -1321,15 +1406,20 @@ xml_optionstr(
 
     if(dp->index) {
        index_opt = "  <index>YES</index>\n";
+    } else {
+       index_opt = "";
     }
 
     if (dp->kencrypt) {
        kencrypt_opt = "  <kencrypt>YES</kencrypt>\n";
+    } else {
+       kencrypt_opt = "";
     }
 
     if (am_has_feature(their_features, fe_xml_data_path)) {
        switch(dp->data_path) {
        case DATA_PATH_AMANDA:
+           amfree(data_path_opt);
            data_path_opt = stralloc("  <datapath>AMANDA</datapath>\n");
            break;
        case DATA_PATH_DIRECTTCP:
@@ -1338,6 +1428,7 @@ xml_optionstr(
                char *s, *sc;
                char *value, *b64value;
 
+               amfree(data_path_opt);
                data_path_opt = stralloc("  <datapath>DIRECTTCP");
                if (dp->dataport_list) {
                    s = sc = stralloc(dp->dataport_list);
@@ -1441,6 +1532,7 @@ xml_optionstr(
     amfree(qdpname);
     amfree(auth_opt);
     amfree(data_path_opt);
+    amfree(compress_opt);
     amfree(exclude);
     amfree(exclude_list);
     amfree(exclude_file);
@@ -1450,11 +1542,27 @@ xml_optionstr(
     amfree(exc);
     amfree(decrypt_opt);
     amfree(encrypt_opt);
+    amfree(script_opt);
 
     /* result contains at least 'auth=...' */
     return result;
 }
 
+char *
+xml_dumptype_properties(
+    disk_t *dp)
+{
+    xml_app_t xml_dumptype;
+
+    xml_dumptype.result = g_strdup("");
+    xml_dumptype.features = NULL;
+    if (dp && dp->config) {
+       g_hash_table_foreach(dumptype_get_property(dp->config), xml_property,
+                            &xml_dumptype);
+    }
+    return xml_dumptype.result;
+}
+
 char *
 xml_estimate(
     estimatelist_t estimatelist,
@@ -1493,10 +1601,13 @@ xml_estimate(
 
 char *
 clean_dle_str_for_client(
-    char *dle_str)
+    char *dle_str,
+    am_feature_t *their_features)
 {
     char *rval_dle_str;
     char *hack1, *hack2;
+    char *pend, *pscript, *pproperty, *eproperty;
+    int len;
 
     if (!dle_str)
        return NULL;
@@ -1516,45 +1627,39 @@ clean_dle_str_for_client(
 #undef SC
 #undef SC_LEN
 
-    return rval_dle_str;
-}
-
-typedef struct {
-    am_feature_t  *features;
-    char          *result;
-} xml_app_t;
-
-/* A GHFunc (callback for g_hash_table_foreach) */
-static void xml_property(
-    gpointer key_p,
-    gpointer value_p,
-    gpointer user_data_p)
-{
-    char       *property_s = key_p;
-    char       *b64property;
-    property_t *property = value_p;
-    char       *b64value_data;
-    xml_app_t  *xml_app = user_data_p;
-    GSList     *value;
-
-    b64property = amxml_format_tag("name", property_s);
-    vstrextend(&xml_app->result, "    <property>\n",
-                               "      ", b64property, "\n", NULL);
-    // TODO if client have fe_xml_property_priority
-    if (property->priority &&
-       am_has_feature(xml_app->features, fe_xml_property_priority)) {
-       vstrextend(&xml_app->result, "      <priority>yes</priority>\n", NULL);
-    }
-    for(value = property->values; value != NULL; value = value->next) {
-       b64value_data = amxml_format_tag("value", value->data);
-       vstrextend(&xml_app->result, "      ", b64value_data, "\n", NULL);
-       amfree(b64value_data);
+    if (!am_has_feature(their_features, fe_dumptype_property)) {
+#define SC "</property>\n"
+#define SC_LEN strlen(SC)
+       /* remove all dle properties, they are before backup-program or script
+         properties */
+       hack1 = rval_dle_str;
+       pend = strstr(rval_dle_str, "<backup-program>");
+       pscript = strstr(rval_dle_str, "<script>");
+       if (pscript && pscript < pend)
+           pend = pscript;
+       if (!pend) /* the complete string */
+           pend = rval_dle_str + strlen(rval_dle_str);
+       while (hack1) {
+           pproperty = strstr(hack1, "    <property>");
+           if (pproperty && pproperty < pend) { /* remove it */
+               eproperty = strstr(pproperty, SC);
+               len = eproperty + SC_LEN - pproperty;
+               memmove(pproperty, eproperty + SC_LEN, strlen(eproperty + SC_LEN) + 1);
+               pend  -= len;
+               hack1 = pproperty;
+           } else {
+               hack1 = NULL;
+           }
+       }
+    } else {
     }
-    vstrextend(&xml_app->result, "    </property>\n", NULL);
+#undef SC
+#undef SC_LEN
 
-    amfree(b64property);
+    return rval_dle_str;
 }
 
+
 char *
 xml_application(
     disk_t        *dp G_GNUC_UNUSED,
@@ -1563,6 +1668,7 @@ xml_application(
 {
     char       *plugin;
     char       *b64plugin;
+    char       *client_name;
     xml_app_t   xml_app;
     proplist_t  proplist;
 
@@ -1576,6 +1682,13 @@ xml_application(
     proplist = application_get_property(application);
     g_hash_table_foreach(proplist, xml_property, &xml_app);
 
+    client_name = application_get_client_name(application);
+    if (client_name && strlen(client_name) > 0 &&
+       am_has_feature(their_features, fe_application_client_name)) {
+       char *b64client_name = amxml_format_tag("client_name", client_name);
+       vstrextend(&xml_app.result, "    ", b64client_name, "\n", NULL);
+    }
+
     vstrextend(&xml_app.result, "  </backup-program>\n", NULL);
 
     amfree(b64plugin);
@@ -1583,7 +1696,7 @@ xml_application(
     return xml_app.result;
 }
 
+
 char *
 xml_scripts(
     identlist_t pp_scriptlist,
@@ -1591,6 +1704,7 @@ xml_scripts(
 {
     char       *plugin;
     char       *b64plugin;
+    char       *client_name;
     char       *xml_scr;
     char       *xml_scr1;
     char       *str = "";
@@ -1627,7 +1741,7 @@ xml_scripts(
 
        execute_on = pp_script_get_execute_on(pp_script);
        sep = "";
-       eo_str = NULL;
+       eo_str = stralloc("");
        if (execute_on & EXECUTE_ON_PRE_DLE_AMCHECK) {
            eo_str = vstrextend(&eo_str, sep, "PRE-DLE-AMCHECK", NULL);
            sep = ",";
@@ -1704,9 +1818,19 @@ xml_scripts(
        proplist = pp_script_get_property(pp_script);
        xml_app.result   = stralloc("");
        g_hash_table_foreach(proplist, xml_property, &xml_app);
+
+       client_name = pp_script_get_client_name(pp_script);
+       if (client_name && strlen(client_name) > 0 &&
+           am_has_feature(their_features, fe_script_client_name)) {
+           char *b64client_name = amxml_format_tag("client_name",
+                                                   client_name);
+           vstrextend(&xml_app.result, "    ", b64client_name, "\n", NULL);
+       }
+
        xml_scr = vstrextend(&xml_scr, xml_scr1, xml_app.result, "  </script>\n", NULL);
        amfree(b64plugin);
        amfree(xml_app.result);
+       amfree(xml_scr1);
     }
     return xml_scr;
 }
@@ -1728,6 +1852,7 @@ disable_skip_disk(
 char *
 match_disklist(
     disklist_t *origqp,
+    gboolean    exact_match,
     int                sargc,
     char **    sargv)
 {
@@ -1739,10 +1864,24 @@ match_disklist(
     int prev_match;
     disk_t *dp_skip;
     disk_t *dp;
+    char **new_sargv = NULL;
 
     if(sargc <= 0)
        return NULL;
 
+    if (exact_match) {
+       new_sargv = g_new0(char *, sargc+1);
+       for (i=0; i<sargc; i++) {
+           if (*sargv[i] == '=') {
+               new_sargv[i] = g_strdup(sargv[i]);
+           } else {
+               new_sargv[i] = g_strconcat("=", sargv[i], NULL);
+           }
+       }
+       sargv = new_sargv;
+    }
+
+
     for(dp = origqp->head; dp != NULL; dp = dp->next) {
        if(dp->todo == 1)
            dp->todo = -1;
@@ -1771,10 +1910,13 @@ match_disklist(
                        dp->todo = 1;
                        match_a_disk = 1;
                        prev_match = 0;
-                   } else { /* dp->todo == 0 */
+                   } else if (dp->todo == 0) {
                        match_a_disk = 1;
                        prev_match = 0;
                        dp_skip = dp;
+                   } else { /* dp->todo == 1 */
+                       match_a_disk = 1;
+                       prev_match = 0;
                    }
                }
            }
@@ -1845,9 +1987,46 @@ match_disklist(
            dp->todo = 0;
     }
 
+    if (new_sargv) {
+       for (i=0; i<sargc; i++)
+           g_free(new_sargv[i]);
+       g_free(new_sargv);
+    }
     return errstr;
 }
 
+gboolean
+match_dumpfile(
+    dumpfile_t  *file,
+    gboolean   exact_match,
+    int                sargc,
+    char **    sargv)
+{
+    disk_t d;
+    am_host_t h;
+    disklist_t dl;
+
+    /* rather than try to reproduce the adaptive matching logic in
+     * match_disklist, this simply creates a new, fake disklist with one
+     * element in it, and calls match_disklist directly */
+
+    bzero(&h, sizeof(h));
+    h.hostname = file->name;
+    h.disks = &d;
+
+    bzero(&d, sizeof(d));
+    d.host = &h;
+    d.hostname = file->name;
+    d.name = file->disk;
+    d.device = file->disk;
+    d.todo = 1;
+
+    dl.head = dl.tail = &d;
+
+    (void)match_disklist(&dl, exact_match, sargc, sargv);
+    return d.todo;
+}
+
 netif_t *
 disklist_netifs(void)
 {