/* tdbundump -- construct a tdb from tdbdump output. Heavily based on tdbdump, a simple tdb dump util Copyright (C) Andrew Tridgell 2001 Copyright (C) Simon McVittie 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tdb.h" #define debug_fprintf(file, fmt, ...) do {/*nothing*/} while (0) static void print_data(TDB_DATA d) { unsigned char *p = (unsigned char *)d.dptr; int len = d.dsize; while (len--) { if (isprint(*p) && !strchr("\"\\", *p)) { fputc(*p, stdout); } else { printf("\\%02X", *p); } p++; } } static int append(TDB_DATA *x, size_t *size, int c) { if (!x->dptr || (x->dsize >= *size)) { *size = (*size) * 2; debug_fprintf(stderr, "realloc to: %d\n", *size); x->dptr = realloc(x->dptr, *size); if (x->dptr == NULL) { perror("realloc!"); return 1; } } x->dptr[x->dsize++] = (char)(c & 0xff); return 0; } static int skip_over(const char *str) { unsigned int i; int c; for (i = 0; i < strlen(str); i++) { c = getchar(); if (c == EOF && i == 0) { return EOF; } if (c != str[i]) { fprintf(stderr, "Expected char 0x%x, saw 0x%x\n", str[i], c); return 1; } } return 0; } static const char *before = "{\nkey = \""; static const char *between = "\ndata = \""; static const char *after = "\n}\n"; static int read_hex(void) { int c; c = getchar(); if (c == EOF) { fprintf(stderr, "Unexpected EOF in data\n"); return -1; } else if (c == '"') { fprintf(stderr, "Unexpected \\\" sequence\n"); return -1; } else if ('0' <= c && c <= '9') { return c - '0'; } else if ('A' <= c && c <= 'F') { return c - 'A' + 10; } else if ('a' <= c && c <= 'f') { return c - 'a' + 10; } else { fprintf(stderr, "Invalid hex: %c\n", c); return -1; } } static int read_data(TDB_DATA *x, size_t *size) { int c, low, high; while (1) { c = getchar(); if (c == EOF) { fprintf(stderr, "Unexpected EOF in data\n"); return 1; } else if (c == '"') { return 0; } else if (c == '\\') { high = read_hex(); if (high < 0) { return -1; } high = high << 4; assert(high == (high & 0xf0)); low = read_hex(); if (low < 0) { return -1; } assert(low == (low & 0x0f)); if (append(x, size, (low | high))) return -1; } else { if (append(x, size, c)) return -1; } } } static int undump_tdb(const char *fname) { TDB_CONTEXT *tdb; int i; TDB_DATA key, data; size_t keysize = 16; size_t datasize = 16; key.dptr = NULL; data.dptr = NULL; key.dsize = 0; data.dsize = 0; tdb = tdb_open(fname, 0, 0, O_RDWR|O_CREAT|O_EXCL, 0666); if (!tdb) { perror("tdb_open"); fprintf(stderr, "Failed to open %s\n", fname); return 1; } while (1) { key.dsize = 0; data.dsize = 0; i = skip_over(before); if (i == EOF) { if (tdb_close(tdb)) { fprintf(stderr, "Error closing tdb\n"); return 1; } fprintf(stderr, "EOF\n"); return 0; } else if (i != 0) { return 1; } if (read_data(&key, &keysize) != 0) { return 1; } if (skip_over(between) != 0) { fprintf(stderr, "Error or EOF\n"); return 1; } if (read_data(&data, &datasize) != 0) { return 1; } if (skip_over(after) != 0) { fprintf(stderr, "Error or EOF\n"); return 1; } if (tdb_store(tdb, key, data, TDB_INSERT)) { fprintf(stderr, "TDB error: %s\n", tdb_errorstr(tdb)); } if (tdb_store(tdb, key, data, TDB_MODIFY)) { fprintf(stderr, "TDB error: %s\n", tdb_errorstr(tdb)); } printf("%s", before); print_data(key); printf("\"%s", between); print_data(data); printf("\"%s", after); } } int main(int argc, char *argv[]) { char *fname; if (argc < 2) { printf("Usage: tdbundump dbname < tdbdump_output\n"); exit(1); } fname = argv[1]; return undump_tdb(fname); }