📄 fileheader.c
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * 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 * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. U.M. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team. Its members are listed in a * file named AUTHORS, in the root directory of this distribution. *//* * $Id: fileheader.c 6512 2007-05-24 17:00:24Z ian $ */#include "amanda.h"#include "fileheader.h"#include <glib.h>#include "util.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 *);static char * strquotedstr(void);static ssize_t hexdump(const char *buffer, size_t len);voidfh_init( dumpfile_t *file){ memset(file, '\0', SIZEOF(*file)); file->blocksize = DISK_BLOCK_BYTES;}static voidstrange_header( dumpfile_t *file, const char *buffer, size_t buflen, const char *expected, const char *actual){ if (actual == NULL) actual = "<null>"; if (expected == NULL) expected = "<null>"; g_fprintf(stderr, _("%s: strange amanda header: \"%.*s\"\n"), get_pname(), (int)buflen, buffer); g_fprintf(stderr, _("%s: Expected: \"%s\" Actual: \"%s\"\n"), get_pname(), expected, actual); file->type = F_WEIRD;}voidparse_file_header( const char *buffer, dumpfile_t *file, size_t buflen){ char *buf, *line, *tok, *line1; size_t lsize; char *uqname; int in_quotes; /* put the buffer into a writable chunk of memory and nul-term it */ buf = alloc(buflen + 1); memcpy(buf, buffer, buflen); buf[buflen] = '\0'; fh_init(file); in_quotes = 0; for (line = buf, lsize = 0; lsize < buflen; line++) { if ((*line == '\n') && !in_quotes) break; if (*line == '"') { in_quotes = !in_quotes; } else if ((*line == '\\') && (*(line + 1) == '"')) { line++; lsize++; } lsize++; } *line = '\0'; line1 = alloc(lsize + 1); strncpy(line1, buf, lsize); line1[lsize] = '\0'; *line = '\n'; tok = strtok(line1, " "); if (tok == NULL) { g_fprintf(stderr, _("%s: Empty amanda header: buflen=%zu lsize=%zu\n"), get_pname(), buflen, lsize); hexdump(buffer, lsize); strange_header(file, buffer, buflen, _("<Non-empty line>"), tok); goto out; } if (strcmp(tok, "NETDUMP:") != 0 && strcmp(tok, "AMANDA:") != 0) { amfree(buf); file->type = F_UNKNOWN; amfree(line1); return; } tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<file type>"), tok); goto out; } 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; } tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<date stamp>"), tok); goto out; } strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1); tok = strtok(NULL, " "); if ((tok == NULL) || (strcmp(tok, "TAPE") != 0)) { strange_header(file, buffer, buflen, "TAPE", tok); goto out; } tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<file type>"), tok); goto out; } strncpy(file->name, tok, SIZEOF(file->name) - 1); break; case F_DUMPFILE: case F_CONT_DUMPFILE: case F_SPLIT_DUMPFILE: tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<date stamp>"), tok); goto out; } strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1); tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<file name>"), tok); goto out; } strncpy(file->name, tok, SIZEOF(file->name) - 1); tok = strquotedstr(); if (tok == NULL) { strange_header(file, buffer, buflen, _("<disk name>"), 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; } tok = strtok(NULL, "/"); if ((tok == NULL) || (sscanf(tok, "%d", &file->partnum) != 1)) { strange_header(file, buffer, buflen, _("<part num param>"), tok); goto out; } /* 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, _("<total parts param>"), tok); goto out; } } tok = strtok(NULL, " "); if ((tok == NULL) || (strcmp(tok, "lev") != 0)) { strange_header(file, buffer, buflen, "lev", tok); goto out; } tok = strtok(NULL, " "); if ((tok == NULL) || (sscanf(tok, "%d", &file->dumplevel) != 1)) { strange_header(file, buffer, buflen, _("<dump level param>"), tok); goto out; } tok = strtok(NULL, " "); if ((tok == NULL) || (strcmp(tok, "comp") != 0)) { strange_header(file, buffer, buflen, "comp", tok); goto out; } tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<comp param>"), 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); 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, _("<program name>"), 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, _("<crypt param>"), 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; } /* "srvcompprog" is optional */ if (BSTRNCMP(tok, "server_custom_compress") == 0) { tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<server custom compress param>"), 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, _("<client custom compress param>"), tok); goto out; } strncpy(file->clntcompprog, tok, SIZEOF(file->clntcompprog) - 1); if ((tok = strtok(NULL, " ")) == NULL) break; } /* "srv_encrypt" is optional */ if (BSTRNCMP(tok, "server_encrypt") == 0) { tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<server encrypt param>"), tok); goto out; } strncpy(file->srv_encrypt, tok, SIZEOF(file->srv_encrypt) - 1); if ((tok = strtok(NULL, " ")) == NULL) break; } /* "clnt_encrypt" is optional */ if (BSTRNCMP(tok, "client_encrypt") == 0) { tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<client encrypt param>"), tok); goto out; } strncpy(file->clnt_encrypt, tok, SIZEOF(file->clnt_encrypt) - 1); if ((tok = strtok(NULL, " ")) == NULL) break; } /* "srv_decrypt_opt" is optional */ if (BSTRNCMP(tok, "server_decrypt_option") == 0) { tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<server decrypt param>"), tok); goto out; } strncpy(file->srv_decrypt_opt, tok, SIZEOF(file->srv_decrypt_opt) - 1); if ((tok = strtok(NULL, " ")) == NULL) break; } /* "clnt_decrypt_opt" is optional */ if (BSTRNCMP(tok, "client_decrypt_option") == 0) { tok = strtok(NULL, " "); if (tok == NULL) { strange_header(file, buffer, buflen, _("<client decrypt param>"), tok); goto out; } strncpy(file->clnt_decrypt_opt, tok, SIZEOF(file->clnt_decrypt_opt) - 1); if ((tok = strtok(NULL, " ")) == NULL) break; } 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, _("<DATE>"), tok); } } else { file->datestamp[0] = '\0'; } break; default: strange_header(file, buffer, buflen, _("TAPESTART|DUMPFILE|CONT_DUMPFILE|SPLIT_DUMPFILE|TAPEEND"), tok); goto out; } (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, SIZEOF(SC) - 1) == 0) { line += SIZEOF(SC) - 1; strncpy(file->cont_filename, line, SIZEOF(file->cont_filename) - 1); continue; }#undef SC#define SC "PARTIAL=" if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) { line += SIZEOF(SC) - 1; file->is_partial = !strcasecmp(line, "yes"); continue; }#undef SC#define SC "DUMPER=" if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) { line += SIZEOF(SC) - 1; strncpy(file->dumper, line, SIZEOF(file->dumper) - 1); continue; }#undef SC#define SC _("To restore, position tape at start of file and run:") if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) continue;#undef SC#define SC "\tdd if=<tape> bs=" 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; } *cmd1++ = '\0'; /* block out first pipeline command */ if ((cmd2 = strchr(cmd1, '|')) != NULL) { *cmd2++ = '\0'; if ((cmd3 = strchr(cmd2, '|')) != NULL) *cmd3++ = '\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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -