+
+gboolean headers_are_equal(dumpfile_t * a, dumpfile_t * b) {
+ if (a == NULL && b == NULL)
+ return TRUE;
+
+ if (a == NULL || b == NULL)
+ return FALSE;
+
+ if (a->type != b->type) return FALSE;
+ if (strcmp(a->datestamp, b->datestamp)) return FALSE;
+ if (a->dumplevel != b->dumplevel) return FALSE;
+ if (a->compressed != b->compressed) return FALSE;
+ if (a->encrypted != b->encrypted) return FALSE;
+ if (strcmp(a->comp_suffix, b->comp_suffix)) return FALSE;
+ if (strcmp(a->encrypt_suffix, b->encrypt_suffix)) return FALSE;
+ if (strcmp(a->name, b->name)) return FALSE;
+ if (strcmp(a->disk, b->disk)) return FALSE;
+ if (strcmp(a->program, b->program)) return FALSE;
+ if (strcmp(a->application, b->application)) return FALSE;
+ if (strcmp(a->srvcompprog, b->srvcompprog)) return FALSE;
+ if (strcmp(a->clntcompprog, b->clntcompprog)) return FALSE;
+ if (strcmp(a->srv_encrypt, b->srv_encrypt)) return FALSE;
+ if (strcmp(a->clnt_encrypt, b->clnt_encrypt)) return FALSE;
+ if (strcmp(a->recover_cmd, b->recover_cmd)) return FALSE;
+ if (strcmp(a->uncompress_cmd, b->uncompress_cmd)) return FALSE;
+ if (strcmp(a->encrypt_cmd, b->encrypt_cmd)) return FALSE;
+ if (strcmp(a->decrypt_cmd, b->decrypt_cmd)) return FALSE;
+ if (strcmp(a->srv_decrypt_opt, b->srv_decrypt_opt)) return FALSE;
+ if (strcmp(a->clnt_decrypt_opt, b->clnt_decrypt_opt)) return FALSE;
+ if (strcmp(a->cont_filename, b->cont_filename)) return FALSE;
+ if (a->dle_str != b->dle_str && a->dle_str && b->dle_str
+ && strcmp(a->dle_str, b->dle_str)) return FALSE;
+ if (a->is_partial != b->is_partial) return FALSE;
+ if (a->partnum != b->partnum) return FALSE;
+ if (a->totalparts != b->totalparts) return FALSE;
+ if (a->blocksize != b->blocksize) return FALSE;
+
+ return TRUE; /* ok, they're the same */
+}
+
+dumpfile_t * dumpfile_copy(dumpfile_t* source) {
+ dumpfile_t* rval = malloc(sizeof(dumpfile_t));
+ memcpy(rval, source, sizeof(dumpfile_t));
+ if (rval->dle_str) rval->dle_str = stralloc(rval->dle_str);
+ return rval;
+}
+
+void
+dumpfile_copy_in_place(
+ dumpfile_t *dest,
+ dumpfile_t* source)
+{
+ memcpy(dest, source, sizeof(dumpfile_t));
+ if (dest->dle_str) dest->dle_str = stralloc(dest->dle_str);
+}
+
+void dumpfile_free_data(dumpfile_t* info) {
+ if (info) {
+ amfree(info->dle_str);
+ }
+}
+
+void dumpfile_free(dumpfile_t* info) {
+ dumpfile_free_data(info);
+ amfree(info);
+}
+
+static ssize_t
+hexdump(
+ const char *buffer,
+ size_t len)
+{
+ ssize_t rc = -1;
+
+ FILE *stream = popen("od -c -x -", "w");
+
+ if (stream != NULL) {
+ fflush(stdout);
+ rc = (ssize_t)fwrite(buffer, len, 1, stream);
+ if (ferror(stream))
+ rc = -1;
+ pclose(stream);
+ }
+ return rc;
+}
+
+static char *quote_heredoc(
+ char *text,
+ char *delimiter_prefix)
+{
+ char *delimiter = stralloc(delimiter_prefix);
+ int delimiter_n = 0;
+ int delimiter_len = strlen(delimiter);
+ char *quoted;
+
+ /* keep picking delimiters until we find one that's not a line in TEXT */
+ while (1) {
+ char *line = text;
+ char *c = text;
+ gboolean found_delimiter = FALSE;
+
+ while (1) {
+ if (*c == '\n' || *c == '\0') {
+ int linelen = c - line;
+ if (linelen == delimiter_len && 0 == strncmp(line, delimiter, linelen)) {
+ found_delimiter = TRUE;
+ break;
+ }
+ line = c+1;
+ }
+ if (!*c) break;
+ c++;
+ }
+
+ if (!found_delimiter)
+ break;
+
+ delimiter = newvstrallocf(delimiter, "%s%d", delimiter_prefix, ++delimiter_n);
+ delimiter_len = strlen(delimiter);
+ }
+
+ /* we have a delimiter .. now use it */
+ quoted = vstrallocf("<<%s\n%s\n%s", delimiter, text, delimiter);
+ amfree(delimiter);
+ return quoted;
+}
+
+static char *parse_heredoc(
+ char *line,
+ char **saveptr)
+{
+ char *result = NULL;
+
+ if (strncmp(line, "<<", 2) == 0) {
+ char *keyword = line+2;
+ char *new_line;
+
+ while((new_line = strtok_r(NULL, "\n", saveptr)) != NULL &&
+ strcmp(new_line, keyword) != 0) {
+ result = vstrextend(&result, new_line, "\n", NULL);
+ }
+ /* remove latest '\n' */
+ if (strlen(result) > 0)
+ result[strlen(result)-1] = '\0';
+ } else {
+ result = stralloc(line);
+ }
+ return result;
+}