X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=common-src%2Ffileheader.c;h=f6786a891cb128ee7ab5dbb01f9c94167ac30b2b;hb=refs%2Ftags%2Fupstream%2F2.5.1p1;hp=928a37c04fa2aba2461a143379a3b5a773942eeb;hpb=3ab887b9bc819a846c75dd7f2ee5d41fac22b19f;p=debian%2Famanda diff --git a/common-src/fileheader.c b/common-src/fileheader.c index 928a37c..f6786a8 100644 --- a/common-src/fileheader.c +++ b/common-src/fileheader.c @@ -1,6 +1,6 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver - * Copyright (c) 1991-1998 University of Maryland at College Park + * Copyright (c) 1991-1999 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -24,438 +24,767 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: fileheader.c,v 1.11.4.1.4.1.2.6 2003/10/24 13:44:49 martinea Exp $ - * + * $Id: fileheader.c,v 1.40 2006/07/01 00:10:38 paddy_s Exp $ */ #include "amanda.h" #include "fileheader.h" +static const char * filetype2str(filetype_t); +static filetype_t str2filetype(const char *); +static void strange_header(dumpfile_t *, const char *, + size_t, const char *, const char *); -void fh_init(file) -dumpfile_t *file; +void +fh_init( + dumpfile_t *file) { - memset(file,'\0',sizeof(*file)); + memset(file, '\0', SIZEOF(*file)); file->blocksize = DISK_BLOCK_BYTES; } +static void +strange_header( + dumpfile_t *file, + const char *buffer, + size_t buflen, + const char *expected, + const char *actual) +{ + if (actual == NULL) + actual = ""; + if (expected == NULL) + expected = ""; + + fprintf(stderr, "%s: strange amanda header: \"%.*s\"\n", get_pname(), + (int)buflen, buffer); + + fprintf(stderr, "%s: Expected: \"%s\" Actual: \"%s\"\n", get_pname(), + expected, actual); + + file->type = F_WEIRD; +} + void -parse_file_header(buffer, file, buflen) - char *buffer; - dumpfile_t *file; - size_t buflen; +parse_file_header( + const char *buffer, + dumpfile_t *file, + size_t buflen) { - string_t line, save_line; - char *bp, *str, *ptr_buf, *start_buf; - int nchars; - char *verify; - char *s, *s1, *s2; - int ch; - int done; - - /* isolate first line */ - - nchars = buflen", tok); + goto out; } - line[sizeof(line)-1] = '\0'; - strncpy(save_line, line, sizeof(save_line)); - - fh_init(file); - s = line; - ch = *s++; - - skip_whitespace(s, ch); - str = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - if(strcmp(str, "NETDUMP:") != 0 && strcmp(str,"AMANDA:") != 0) { + if (strcmp(tok, "NETDUMP:") != 0 && strcmp(tok, "AMANDA:") != 0) { + amfree(buf); file->type = F_UNKNOWN; + amfree(line1); return; } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; } - str = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - - if(strcmp(str, "TAPESTART") == 0) { - file->type = F_TAPESTART; - - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - verify = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - if(strcmp(verify, "DATE") != 0) { - goto weird_header; + file->type = str2filetype(tok); + + switch (file->type) { + case F_TAPESTART: + tok = strtok(NULL, " "); + if ((tok == NULL) || (strcmp(tok, "DATE") != 0)) { + strange_header(file, buffer, buflen, "DATE", tok); + goto out; } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - copy_string(s, ch, file->datestamp, sizeof(file->datestamp), bp); - if(bp == NULL) { - goto weird_header; + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; } + strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1); - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - verify = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - if(strcmp(verify, "TAPE") != 0) { - goto weird_header; + tok = strtok(NULL, " "); + if ((tok == NULL) || (strcmp(tok, "TAPE") != 0)) { + strange_header(file, buffer, buflen, "TAPE", tok); + goto out; } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - copy_string(s, ch, file->name, sizeof(file->name), bp); - if(bp == NULL) { - goto weird_header; + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; } - } else if(strcmp(str, "FILE") == 0 || - strcmp(str, "CONT_FILE") == 0) { - if(strcmp(str, "FILE") == 0) - file->type = F_DUMPFILE; - else if(strcmp(str, "CONT_FILE") == 0) - file->type = F_CONT_DUMPFILE; + strncpy(file->name, tok, SIZEOF(file->name) - 1); + break; - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - copy_string(s, ch, file->datestamp, sizeof(file->datestamp), bp); - if(bp == NULL) { - goto weird_header; - } + case F_DUMPFILE: + case F_CONT_DUMPFILE: + case F_SPLIT_DUMPFILE: + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; + } + strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1); + + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; + } + strncpy(file->name, tok, SIZEOF(file->name) - 1); + + tok = strquotedstr(); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; + } + uqname = unquote_string(tok); + strncpy(file->disk, uqname, SIZEOF(file->disk) - 1); + amfree(uqname); + + if(file->type == F_SPLIT_DUMPFILE) { + tok = strtok(NULL, " "); + if (tok == NULL || strcmp(tok, "part") != 0) { + strange_header(file, buffer, buflen, "part", tok); + goto out; + } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - copy_string(s, ch, file->name, sizeof(file->name), bp); - if(bp == NULL) { - goto weird_header; - } + tok = strtok(NULL, "/"); + if ((tok == NULL) || (sscanf(tok, "%d", &file->partnum) != 1)) { + strange_header(file, buffer, buflen, "", tok); + goto out; + } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - copy_string(s, ch, file->disk, sizeof(file->disk), bp); - if(bp == NULL) { - goto weird_header; + /* If totalparts == -1, then the original dump was done in + streaming mode (no holding disk), thus we don't know how + many parts there are. */ + tok = strtok(NULL, " "); + if((tok == NULL) || (sscanf(tok, "%d", &file->totalparts) != 1)) { + strange_header(file, buffer, buflen, "", tok); + goto out; + } } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - verify = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - if(strcmp(verify, "lev") != 0) { - goto weird_header; + tok = strtok(NULL, " "); + if ((tok == NULL) || (strcmp(tok, "lev") != 0)) { + strange_header(file, buffer, buflen, "lev", tok); + goto out; } - skip_whitespace(s, ch); - if(ch == '\0' || sscanf(s - 1, "%d", &file->dumplevel) != 1) { - goto weird_header; + tok = strtok(NULL, " "); + if ((tok == NULL) || (sscanf(tok, "%d", &file->dumplevel) != 1)) { + strange_header(file, buffer, buflen, "", tok); + goto out; } - skip_integer(s, ch); - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - verify = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - if(strcmp(verify, "comp") != 0) { - goto weird_header; + tok = strtok(NULL, " "); + if ((tok == NULL) || (strcmp(tok, "comp") != 0)) { + strange_header(file, buffer, buflen, "comp", tok); + goto out; } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - copy_string(s, ch, file->comp_suffix, sizeof(file->comp_suffix), bp); - if(bp == NULL) { - goto weird_header; + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; } + strncpy(file->comp_suffix, tok, SIZEOF(file->comp_suffix) - 1); file->compressed = strcmp(file->comp_suffix, "N"); /* compatibility with pre-2.2 amanda */ - if(strcmp(file->comp_suffix, "C") == 0) { - strncpy(file->comp_suffix, ".Z", sizeof(file->comp_suffix)-1); - file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0'; + if (strcmp(file->comp_suffix, "C") == 0) + strncpy(file->comp_suffix, ".Z", SIZEOF(file->comp_suffix) - 1); + + tok = strtok(NULL, " "); + /* "program" is optional */ + if (tok == NULL || strcmp(tok, "program") != 0) { + amfree(buf); + amfree(line1); + return; + } + + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; + } + strncpy(file->program, tok, SIZEOF(file->program) - 1); + if (file->program[0] == '\0') + strncpy(file->program, "RESTORE", SIZEOF(file->program) - 1); + + if ((tok = strtok(NULL, " ")) == NULL) + break; /* reached the end of the buffer */ + + /* "encryption" is optional */ + if (BSTRNCMP(tok, "crypt") == 0) { + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, "", tok); + goto out; + } + strncpy(file->encrypt_suffix, tok, + SIZEOF(file->encrypt_suffix) - 1); + file->encrypted = BSTRNCMP(file->encrypt_suffix, "N"); + if ((tok = strtok(NULL, " ")) == NULL) + break; } - skip_whitespace(s, ch); - if(ch == '\0') { - return; /* "program" is optional */ - } - verify = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - if(strcmp(verify, "program") != 0) { - return; /* "program" is optional */ + /* "srvcompprog" is optional */ + if (BSTRNCMP(tok, "server_custom_compress") == 0) { + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, + "", tok); + goto out; + } + strncpy(file->srvcompprog, tok, SIZEOF(file->srvcompprog) - 1); + if ((tok = strtok(NULL, " ")) == NULL) + break; + } + + /* "clntcompprog" is optional */ + if (BSTRNCMP(tok, "client_custom_compress") == 0) { + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, + "", tok); + goto out; + } + strncpy(file->clntcompprog, tok, SIZEOF(file->clntcompprog) - 1); + if ((tok = strtok(NULL, " ")) == NULL) + break; } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - copy_string(s, ch, file->program, sizeof(file->program), bp); - if(bp == NULL) { - goto weird_header; + /* "srv_encrypt" is optional */ + if (BSTRNCMP(tok, "server_encrypt") == 0) { + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, + "", tok); + goto out; + } + strncpy(file->srv_encrypt, tok, SIZEOF(file->srv_encrypt) - 1); + if ((tok = strtok(NULL, " ")) == NULL) + break; } - if(file->program[0]=='\0') { - strncpy(file->program, "RESTORE", sizeof(file->program)-1); - file->program[sizeof(file->program)-1] = '\0'; + /* "clnt_encrypt" is optional */ + if (BSTRNCMP(tok, "client_encrypt") == 0) { + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, + "", tok); + goto out; + } + strncpy(file->clnt_encrypt, tok, SIZEOF(file->clnt_encrypt) - 1); + if ((tok = strtok(NULL, " ")) == NULL) + break; } - } else if(strcmp(str, "TAPEEND") == 0) { - file->type = F_TAPEEND; - - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; - } - verify = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - if(strcmp(verify, "DATE") != 0) { - return; /* "program" is optional */ + /* "srv_decrypt_opt" is optional */ + if (BSTRNCMP(tok, "server_decrypt_option") == 0) { + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, + "", tok); + goto out; + } + strncpy(file->srv_decrypt_opt, tok, + SIZEOF(file->srv_decrypt_opt) - 1); + if ((tok = strtok(NULL, " ")) == NULL) + break; } - skip_whitespace(s, ch); - if(ch == '\0') { - goto weird_header; + /* "clnt_decrypt_opt" is optional */ + if (BSTRNCMP(tok, "client_decrypt_option") == 0) { + tok = strtok(NULL, " "); + if (tok == NULL) { + strange_header(file, buffer, buflen, + "", tok); + goto out; + } + strncpy(file->clnt_decrypt_opt, tok, + SIZEOF(file->clnt_decrypt_opt) - 1); + if ((tok = strtok(NULL, " ")) == NULL) + break; } - copy_string(s, ch, file->datestamp, sizeof(file->datestamp), bp); - if(bp == NULL) { - goto weird_header; + break; + + + case F_TAPEEND: + tok = strtok(NULL, " "); + /* DATE is optional */ + if (tok != NULL) { + if (strcmp(tok, "DATE") == 0) { + tok = strtok(NULL, " "); + if(tok == NULL) + file->datestamp[0] = '\0'; + else + strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1); + } else { + strange_header(file, buffer, buflen, "", tok); + } + } else { + file->datestamp[0] = '\0'; } - } else { - goto weird_header; + break; + + default: + strange_header(file, buffer, buflen, + "TAPESTART|DUMPFILE|CONT_DUMPFILE|SPLIT_DUMPFILE|TAPEEND", tok); + goto out; } - done=0; - do { - /* isolate the next line */ - int max_char; - ptr_buf++; - start_buf = ptr_buf; - max_char = buflen - (ptr_buf - buffer); - nchars = max_char= start_buf+nchars) done = 1; - line[sizeof(line)-1] = '\0'; - s = line; - ch = *s++; + (void)strtok(buf, "\n"); /* this is the first line */ + /* iterate through the rest of the lines */ + while ((line = strtok(NULL, "\n")) != NULL) { #define SC "CONT_FILENAME=" - if(strncmp(line,SC,strlen(SC)) == 0) { - s = line + strlen(SC); - ch = *s++; - copy_string(s, ch, file->cont_filename, - sizeof(file->cont_filename), bp); + if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) { + line += SIZEOF(SC) - 1; + strncpy(file->cont_filename, line, + SIZEOF(file->cont_filename) - 1); + continue; } #undef SC + #define SC "PARTIAL=" - else if(strncmp(line,SC,strlen(SC)) == 0) { - s = line + strlen(SC); - if(strncmp(s,"yes",3)==0 || strncmp(s,"YES",3)==0) - file->is_partial=1; - ch = *s++; + if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) { + line += SIZEOF(SC) - 1; + file->is_partial = !strcasecmp(line, "yes"); + continue; } #undef SC + #define SC "To restore, position tape at start of file and run:" - else if(strncmp(line,SC,strlen(SC)) == 0) { - } + if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) + continue; #undef SC + #define SC "\tdd if= bs=" - else if(strncmp(line,SC,strlen(SC)) == 0) { - s = strtok(line, "|"); - s1 = strtok(NULL, "|"); - s2 = strtok(NULL, "|"); - if(!s1) { - strncpy(file->recover_cmd,"BUG",sizeof(file->recover_cmd)); - file->recover_cmd[sizeof(file->recover_cmd)-1] = '\0'; + if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) { + char *cmd1, *cmd2, *cmd3=NULL; + + /* skip over dd command */ + if ((cmd1 = strchr(line, '|')) == NULL) { + + strncpy(file->recover_cmd, "BUG", + SIZEOF(file->recover_cmd) - 1); + continue; } - else if(!s2) { - strncpy(file->recover_cmd,s1+1,sizeof(file->recover_cmd)); - file->recover_cmd[sizeof(file->recover_cmd)-1] = '\0'; + *cmd1++ = '\0'; + + /* block out first pipeline command */ + if ((cmd2 = strchr(cmd1, '|')) != NULL) { + *cmd2++ = '\0'; + if ((cmd3 = strchr(cmd2, '|')) != NULL) + *cmd3++ = '\0'; } - else { - strncpy(file->uncompress_cmd,s1, sizeof(file->uncompress_cmd)); - file->uncompress_cmd[sizeof(file->uncompress_cmd)-2] = '\0'; - strcat(file->uncompress_cmd,"|"); - strncpy(file->recover_cmd,s2+1,sizeof(file->recover_cmd)); - file->recover_cmd[sizeof(file->recover_cmd)-1] = '\0'; + + /* three cmds: decrypt | uncompress | recover + * two cmds: uncompress | recover + * XXX note that if there are two cmds, the first one + * XXX could be either uncompress or decrypt. Since no + * XXX code actually call uncompress_cmd/decrypt_cmd, it's ok + * XXX for header information. + * one cmds: recover + */ + + if ( cmd3 == NULL) { + if (cmd2 == NULL) { + strncpy(file->recover_cmd, cmd1, + SIZEOF(file->recover_cmd) - 1); + } else { + snprintf(file->uncompress_cmd, + SIZEOF(file->uncompress_cmd), "%s|", cmd1); + strncpy(file->recover_cmd, cmd2, + SIZEOF(file->recover_cmd) - 1); + } + } else { /* cmd3 presents: decrypt | uncompress | recover */ + snprintf(file->decrypt_cmd, + SIZEOF(file->decrypt_cmd), "%s|", cmd1); + snprintf(file->uncompress_cmd, + SIZEOF(file->uncompress_cmd), "%s|", cmd2); + strncpy(file->recover_cmd, cmd3, + SIZEOF(file->recover_cmd) - 1); } + continue; } #undef SC - else { /* ignore unknown line */ - } - } while(!done); + /* XXX complain about weird lines? */ + } - return; +out: + amfree(buf); + amfree(line1); +} - weird_header: +void +dump_dumpfile_t( + const dumpfile_t *file) +{ + const char *pname = get_pname(); + + dbprintf(("%s: Contents of *(dumpfile_t *)%p:\n", pname, file)); + dbprintf(("%s: type = %d (%s)\n", pname, + file->type, filetype2str(file->type))); + dbprintf(("%s: datestamp = '%s'\n", pname, + file->datestamp)); + dbprintf(("%s: dumplevel = %d\n", pname, file->dumplevel)); + dbprintf(("%s: compressed = %d\n", pname, file->compressed)); + dbprintf(("%s: encrypted = %d\n", pname, file->encrypted)); + dbprintf(("%s: comp_suffix = '%s'\n", pname, + file->comp_suffix)); + dbprintf(("%s: encrypt_suffix = '%s'\n", pname, + file->encrypt_suffix)); + dbprintf(("%s: name = '%s'\n", pname, file->name)); + dbprintf(("%s: disk = '%s'\n", pname, file->disk)); + dbprintf(("%s: program = '%s'\n", pname, file->program)); + dbprintf(("%s: srvcompprog = '%s'\n", pname, + file->srvcompprog)); + dbprintf(("%s: clntcompprog = '%s'\n", pname, + file->clntcompprog)); + dbprintf(("%s: srv_encrypt = '%s'\n", pname, + file->srv_encrypt)); + dbprintf(("%s: clnt_encrypt = '%s'\n", pname, + file->clnt_encrypt)); + dbprintf(("%s: recover_cmd = '%s'\n", pname, + file->recover_cmd)); + dbprintf(("%s: uncompress_cmd = '%s'\n", pname, + file->uncompress_cmd)); + dbprintf(("%s: encrypt_cmd = '%s'\n", pname, + file->encrypt_cmd)); + dbprintf(("%s: decrypt_cmd = '%s'\n", pname, + file->decrypt_cmd)); + dbprintf(("%s: srv_decrypt_opt = '%s'\n", pname, + file->srv_decrypt_opt)); + dbprintf(("%s: clnt_decrypt_opt = '%s'\n", pname, + file->clnt_decrypt_opt)); + dbprintf(("%s: cont_filename = '%s'\n", pname, + file->cont_filename)); + dbprintf(("%s: is_partial = %d\n", pname, file->is_partial)); + dbprintf(("%s: partnum = %d\n", pname, file->partnum)); + dbprintf(("%s: totalparts = %d\n", pname, file->totalparts)); + dbprintf(("%s: blocksize = " SIZE_T_FMT "\n", pname, + (SIZE_T_FMT_TYPE)file->blocksize)); +} - fprintf(stderr, "%s: strange amanda header: \"%s\"\n", get_pname(), save_line); - file->type = F_WEIRD; - return; +static void +validate_name( + const char *name) +{ + if (strlen(name) == 0) { + error("Invalid name '%s'\n", name); + /*NOTREACHED*/ + } +} + +static void +validate_datestamp( + const char *datestamp) +{ + if (strcmp(datestamp, "X") == 0) { + return; + } + + if ((strlen(datestamp) == 8) && match("^[0-9]{8}$", datestamp)) { + return; + } + if ((strlen(datestamp) == 14) && match("^[0-9]{14}$", datestamp)) { + return; + } + error("Invalid datestamp '%s'\n", datestamp); + /*NOTREACHED*/ } +static void +validate_parts( + const int partnum, + const int totalparts) +{ + if (partnum < 1) { + error("Invalid partnum (%d)\n", partnum); + /*NOTREACHED*/ + } + + if (partnum > totalparts && totalparts >= 0) { + error("Invalid partnum (%d) > totalparts (%d)\n", + partnum, totalparts); + /*NOTREACHED*/ + } +} void -build_header(buffer, file, buflen) - char *buffer; - dumpfile_t *file; - size_t buflen; +build_header( + char * buffer, + const dumpfile_t * file, + size_t buflen) { - char *line = NULL; - char number[NUM_STR_SIZE*2]; + int n; + char *qname; + char split_data[128] = ""; + + dbprintf(("%s: Building type %d (%s) header of size " SIZE_T_FMT " using:\n", + get_pname(), file->type, filetype2str(file->type), + (SIZE_T_FMT_TYPE)buflen)); + dump_dumpfile_t(file); memset(buffer,'\0',buflen); switch (file->type) { - case F_TAPESTART: ap_snprintf(buffer, buflen, - "AMANDA: TAPESTART DATE %s TAPE %s\n\014\n", - file->datestamp, file->name); - break; + case F_TAPESTART: + validate_name(file->name); + validate_datestamp(file->datestamp); + snprintf(buffer, buflen, + "AMANDA: TAPESTART DATE %s TAPE %s\n014\n", + file->datestamp, file->name); + break; + + case F_SPLIT_DUMPFILE: + validate_parts(file->partnum, file->totalparts); + snprintf(split_data, SIZEOF(split_data), + " part %d/%d ", file->partnum, file->totalparts); + /*FALLTHROUGH*/ + case F_CONT_DUMPFILE: - case F_DUMPFILE : if( file->type == F_DUMPFILE) { - ap_snprintf(buffer, buflen, - "AMANDA: FILE %s %s %s lev %d comp %s program %s\n", - file->datestamp, file->name, file->disk, - file->dumplevel, file->comp_suffix, - file->program); - } - else if( file->type == F_CONT_DUMPFILE) { - ap_snprintf(buffer, buflen, - "AMANDA: CONT_FILE %s %s %s lev %d comp %s program %s\n", - file->datestamp, file->name, file->disk, - file->dumplevel, file->comp_suffix, - file->program); - } - buffer[buflen-1] = '\0'; - if(strlen(file->cont_filename) != 0) { - line = newvstralloc(line, "CONT_FILENAME=", - file->cont_filename, "\n", NULL); - strncat(buffer,line,buflen-strlen(buffer)); - } - if(file->is_partial != 0) { - strncat(buffer,"PARTIAL=YES\n",buflen-strlen(buffer)); - } - strncat(buffer, - "To restore, position tape at start of file and run:\n", - buflen-strlen(buffer)); - ap_snprintf(number, sizeof(number), - "%ld", file->blocksize / 1024); - line = newvstralloc(line, "\t", - "dd", - " if=", - " bs=", number, "k", - " skip=1", - " |", file->uncompress_cmd, - " ", file->recover_cmd, - "\n", - "\014\n", /* ?? */ - NULL); - strncat(buffer, line, buflen-strlen(buffer)); - amfree(line); - buffer[buflen-1] = '\0'; - break; - case F_TAPEEND : ap_snprintf(buffer, buflen, - "AMANDA: TAPEEND DATE %s\n\014\n", - file->datestamp); - break; - case F_UNKNOWN : break; - case F_WEIRD : break; + case F_DUMPFILE : + validate_name(file->name); + validate_datestamp(file->datestamp); + qname = quote_string(file->disk); + n = snprintf(buffer, buflen, + "AMANDA: %s %s %s %s %s lev %d comp %s program %s", + filetype2str(file->type), + file->datestamp, file->name, qname, + split_data, + file->dumplevel, file->comp_suffix, file->program); + amfree(qname); + if ( n ) { + buffer += n; + buflen -= n; + n = 0; + } + + if (strcmp(file->encrypt_suffix, "enc") == 0) { /* only output crypt if it's enabled */ + n = snprintf(buffer, buflen, " crypt %s", file->encrypt_suffix); + } + if ( n ) { + buffer += n; + buflen -= n; + n = 0; + } + + if (*file->srvcompprog) { + n = snprintf(buffer, buflen, " server_custom_compress %s", file->srvcompprog); + } else if (*file->clntcompprog) { + n = snprintf(buffer, buflen, " client_custom_compress %s", file->clntcompprog); + } + + if ( n ) { + buffer += n; + buflen -= n; + n = 0; + } + + if (*file->srv_encrypt) { + n = snprintf(buffer, buflen, " server_encrypt %s", file->srv_encrypt); + } else if (*file->clnt_encrypt) { + n = snprintf(buffer, buflen, " client_encrypt %s", file->clnt_encrypt); + } + + if ( n ) { + buffer += n; + buflen -= n; + n = 0; + } + + if (*file->srv_decrypt_opt) { + n = snprintf(buffer, buflen, " server_decrypt_option %s", file->srv_decrypt_opt); + } else if (*file->clnt_decrypt_opt) { + n = snprintf(buffer, buflen, " client_decrypt_option %s", file->clnt_decrypt_opt); + } + + if ( n ) { + buffer += n; + buflen -= n; + n = 0; + } + + n = snprintf(buffer, buflen, "\n"); + buffer += n; + buflen -= n; + + if (file->cont_filename[0] != '\0') { + n = snprintf(buffer, buflen, "CONT_FILENAME=%s\n", + file->cont_filename); + buffer += n; + buflen -= n; + } + if (file->is_partial != 0) { + n = snprintf(buffer, buflen, "PARTIAL=YES\n"); + buffer += n; + buflen -= n; + } + + n = snprintf(buffer, buflen, + "To restore, position tape at start of file and run:\n"); + buffer += n; + buflen -= n; + + /* \014 == ^L == form feed */ + n = snprintf(buffer, buflen, + "\tdd if= bs=" SIZE_T_FMT "k skip=1 | %s %s %s\n\014\n", + (SIZE_T_FMT_TYPE)file->blocksize / 1024, file->decrypt_cmd, + file->uncompress_cmd, file->recover_cmd); + break; + + case F_TAPEEND: + validate_datestamp(file->datestamp); + snprintf(buffer, buflen, "AMANDA: TAPEEND DATE %s\n\014\n", + file->datestamp); + break; + + case F_UNKNOWN: + case F_EMPTY: + case F_WEIRD: + default: + error("Invalid header type: %d (%s)", + file->type, filetype2str(file->type)); + /*NOTREACHED*/ } } - -void print_header(outf, file) -FILE *outf; -dumpfile_t *file; /* * Prints the contents of the file structure. */ +void +print_header( + FILE * outf, + const dumpfile_t * file) { + char *qdisk; + char number[NUM_STR_SIZE*2]; + switch(file->type) { + case F_EMPTY: + fprintf(outf, "EMPTY file\n"); + break; + case F_UNKNOWN: fprintf(outf, "UNKNOWN file\n"); break; + case F_WEIRD: fprintf(outf, "WEIRD file\n"); break; + case F_TAPESTART: fprintf(outf, "start of tape: date %s label %s\n", file->datestamp, file->name); break; + case F_DUMPFILE: - fprintf(outf, "dumpfile: date %s host %s disk %s lev %d comp %s", - file->datestamp, file->name, file->disk, file->dumplevel, - file->comp_suffix); - if(*file->program) - fprintf(outf, " program %s\n",file->program); - else - fprintf(outf, "\n"); - break; case F_CONT_DUMPFILE: - fprintf(outf, "cont dumpfile: date %s host %s disk %s lev %d comp %s", - file->datestamp, file->name, file->disk, file->dumplevel, - file->comp_suffix); - if(*file->program) - fprintf(outf, " program %s\n",file->program); - else - fprintf(outf, "\n"); + qdisk = quote_string(file->disk); + fprintf(outf, "%s: date %s host %s disk %s lev %d comp %s", + filetype2str(file->type), file->datestamp, file->name, + qdisk, file->dumplevel, file->comp_suffix); + if (*file->program) + fprintf(outf, " program %s",file->program); + if (strcmp(file->encrypt_suffix, "enc") == 0) + fprintf(outf, " crypt %s", file->encrypt_suffix); + if (*file->srvcompprog) + fprintf(outf, " server_custom_compress %s", file->srvcompprog); + if (*file->clntcompprog) + fprintf(outf, " client_custom_compress %s", file->clntcompprog); + if (*file->srv_encrypt) + fprintf(outf, " server_encrypt %s", file->srv_encrypt); + if (*file->clnt_encrypt) + fprintf(outf, " client_encrypt %s", file->clnt_encrypt); + if (*file->srv_decrypt_opt) + fprintf(outf, " server_decrypt_option %s", file->srv_decrypt_opt); + if (*file->clnt_decrypt_opt) + fprintf(outf, " client_decrypt_option %s", file->clnt_decrypt_opt); + fprintf(outf, "\n"); + amfree(qdisk); break; + + case F_SPLIT_DUMPFILE: + if(file->totalparts > 0){ + snprintf(number, SIZEOF(number), "%d", file->totalparts); + } + else snprintf(number, SIZEOF(number), "UNKNOWN"); + qdisk = quote_string(file->disk); + fprintf(outf, "split dumpfile: date %s host %s disk %s part %d/%s lev %d comp %s", + file->datestamp, file->name, qdisk, file->partnum, + number, file->dumplevel, file->comp_suffix); + if (*file->program) + fprintf(outf, " program %s",file->program); + if (strcmp(file->encrypt_suffix, "enc") == 0) + fprintf(outf, " crypt %s", file->encrypt_suffix); + if (*file->srvcompprog) + fprintf(outf, " server_custom_compress %s", file->srvcompprog); + if (*file->clntcompprog) + fprintf(outf, " client_custom_compress %s", file->clntcompprog); + if (*file->srv_encrypt) + fprintf(outf, " server_encrypt %s", file->srv_encrypt); + if (*file->clnt_encrypt) + fprintf(outf, " client_encrypt %s", file->clnt_encrypt); + if (*file->srv_decrypt_opt) + fprintf(outf, " server_decrypt_option %s", file->srv_decrypt_opt); + if (*file->clnt_decrypt_opt) + fprintf(outf, " client_decrypt_option %s", file->clnt_decrypt_opt); + fprintf(outf, "\n"); + amfree(qdisk); + break; + case F_TAPEEND: fprintf(outf, "end of tape: date %s\n", file->datestamp); break; } } - -int known_compress_type(file) -dumpfile_t *file; +int +known_compress_type( + const dumpfile_t * file) { if(strcmp(file->comp_suffix, ".Z") == 0) return 1; @@ -463,5 +792,45 @@ dumpfile_t *file; if(strcmp(file->comp_suffix, ".gz") == 0) return 1; #endif + if(strcmp(file->comp_suffix, "cust") == 0) + return 1; return 0; } + +static const struct { + filetype_t type; + const char *str; +} filetypetab[] = { + { F_UNKNOWN, "UNKNOWN" }, + { F_WEIRD, "WEIRD" }, + { F_TAPESTART, "TAPESTART" }, + { F_TAPEEND, "TAPEEND" }, + { F_DUMPFILE, "FILE" }, + { F_CONT_DUMPFILE, "CONT_FILE" }, + { F_SPLIT_DUMPFILE, "SPLIT_FILE" } +}; +#define NFILETYPES (size_t)(sizeof(filetypetab) / sizeof(filetypetab[0])) + +static const char * +filetype2str( + filetype_t type) +{ + int i; + + for (i = 0; i < (int)NFILETYPES; i++) + if (filetypetab[i].type == type) + return (filetypetab[i].str); + return ("UNKNOWN"); +} + +static filetype_t +str2filetype( + const char *str) +{ + int i; + + for (i = 0; i < (int)NFILETYPES; i++) + if (strcmp(filetypetab[i].str, str) == 0) + return (filetypetab[i].type); + return (F_UNKNOWN); +}