tdbexport (was Re: Working on LDAP support in HEAD)
Peter Samuelson
peter at cadcamlab.org
Mon May 15 11:08:31 GMT 2000
[Jean Francois Micouleau <Jean-Francois.Micouleau at dalalu.fr>]
> well, you will still be able to vi the smbpasswd.tdb.
>
> you would have to run: tdbexport smbpasswd|vi|tdbimport smbpasswd
>
> tdbexport and tdbimport are not available but we haven't switch to a
> tdb for password yet.
Here's a tdbexport that seems to be working ok. (As in, no known bugs,
tested on Linux/i386....) I'll write a matching tdbimport when I get a
chance. This file must be compiled with -DSTANDALONE -I. and linked
with tdb.o, just like tdbtool.
It knows four distinct output formats: literal, hex, MIME (RFC-1341)
Base64 and MIME Quoted-Printable. Default is Q-P, because unlike
'literal' it is (I believe) lossless for arbitrary keys and values, and
unlike the others it is human-readable. I know I shouldn't have
bothered with so many output formats; I guess I was bored.
Tridge et al, feel free to put this in CVS if it passes muster.
Peter
/*
* tdbexport.c
* Copyright (C) 2000 Peter Samuelson <peter at cadcamlab.org>
*
* Some bits stolen from tdbtool.c by Andrew Tridgell
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include "tdb.h"
#define MODE_LITERAL 1
#define MODE_HEX 2
#define MODE_BASE64 3
#define MODE_QPRINT 4
#define MODE_ESC_COLON 8 /* flag, so use distinct bit */
const static char *progname = "tdbexport";
static int verbose;
static int line_max = 76; /* for hex and quoted-printable displays */
static int line_len;
static int print_mode = MODE_QPRINT;
static FILE *outfp;
static void do_header(FILE *out, char *filename, int mode)
{
char *fmt;
time_t t = time(0);
switch (mode) {
case MODE_LITERAL: return;
case MODE_HEX: fmt = "Hex-Dump"; break;
case MODE_BASE64: fmt = "Base64"; break;
case MODE_QPRINT: fmt = "Quoted-Printable"; break;
}
fprintf(out,
"; TDB dump file - import with `tdbimport'\n"
"; Source: %s\n"
"; Date: %s" /* ctime adds \n */
"; Format: %s\n\n",
filename, ctime(&t), fmt);
}
static void do_output(FILE *out, char *buf, int len, int mode)
{
int i, esc_colon;
esc_colon = mode & MODE_ESC_COLON;
mode &= ~MODE_ESC_COLON;
switch (mode) {
case MODE_LITERAL: /* literal characters */
fwrite(buf, len, 1, out);
break;
case MODE_HEX: /* hexadecimal */
for (i=0; i<len; i++) {
int ch=buf[i];
fprintf(out, "%02X", ch);
line_len += 2;
if(line_len >= line_max-1) {
fputs("\n ", out);
line_len = 2;
}
}
break;
/*
* MIME Base64 output
* Believed to be basically RFC1341-compliant.
* Should be (had better be!) endian-independent.
*/
case MODE_BASE64:
for (i=0; i<len; i+=3) {
static char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char ch[4], j;
char *fmt;
ch[0] = buf[i];
ch[1] = i+1 < len ? buf[i+1] : 0;
ch[2] = i+2 < len ? buf[i+2] : 0;
ch[3] = base64[ 0x3f & ch[2] ];
ch[2] = base64[ 0x3f & ((ch[1] << 2) | (ch[2] >> 6)) ];
ch[1] = base64[ 0x3f & ((ch[0] << 4) | (ch[1] >> 4)) ];
ch[0] = base64[ ch[0] >> 2 ];
if (i+2 >= len)
ch[3] = '=';
if (i+1 == len)
ch[2] = '=';
switch (line_max - line_len) {
case -1:
case 0: fmt = "\n %c%c%c%c"; line_len=6; break;
case 1: fmt = "%c\n %c%c%c"; line_len=5; break;
case 2: fmt = "%c%c\n %c%c"; line_len=4; break;
case 3: fmt = "%c%c%c\n %c"; line_len=3; break;
default: fmt = "%c%c%c%c"; line_len+=4; break;
}
fprintf(out, fmt, ch[0], ch[1], ch[2], ch[3]);
}
break;
/*
* MIME Quoted-Printable output
* Believed to be RFC1341-compliant.
* Also believed to be lossless for any data,
* which of course is the whole point.
*/
case MODE_QPRINT: /* quoted-printable */
for (i=0; i<len; i++) {
int ch = buf[i];
static char tmpbuf[8];
char *fmt;
if (ch == '\n') {
if (i == len-1) /* final char is newline */
fmt = "=0A";
else
fmt = "=0A=\r\n";
}
else if ((ch == ' ' && i == len-1) || /* space at end of output */
(ch == ':' && esc_colon) || /* colon in first field */
/* line starting with ; or # */
((ch == '#' || ch == ';') && esc_colon && line_len == 0) ||
(ch == '=' || ch < 32 || ch > 127)) /* non-printable character */
fmt = "=%02X";
else
fmt = "%c";
line_len += sprintf(tmpbuf, fmt, ch);
if(line_len >= line_max) {
fputs("=\r\n", out);
line_len = strlen(tmpbuf);
}
fputs(tmpbuf, out);
}
break;
default:
fprintf(stderr, "%s: unknown output mode %d\n", progname, mode);
exit(1);
}
}
/* callback for db traversal */
int export_cb(TDB_CONTEXT *unused1, TDB_DATA key, TDB_DATA dbuf, void *unused2)
{
do_output(outfp, key.dptr, key.dsize, print_mode | MODE_ESC_COLON);
fputc(':', outfp); line_len++;
do_output(outfp, dbuf.dptr, dbuf.dsize, print_mode);
fputc('\n', outfp); line_len = 0;
/* free(key.dptr); // README is wrong */
/* free(dbuf.dptr); // README is wrong */
return 0;
}
static void usage(void)
{
fprintf(stderr,
"usage: %s [-x|-p|-l] [-m N] [-o output] dbfile\n"
" -x output in a hexadecimal format\n"
" -b output in MIME Base64 format\n"
" -p output in MIME Quoted-Printable format\n"
" -l output literal characters (warning: can be lossy!)\n"
" -o name of output file\n"
" -m maximum number of characters per output line\n"
" (ignored in \"literal\" mode)\n"
"The database file is not optional.\n"
"Default output mode is Quoted-Printable.\n", progname);
exit(1);
}
int main(int argc, char *argv[])
{
char *dbfile;
int o;
char *outfile = NULL;
TDB_CONTEXT *t;
while((o=getopt(argc, argv, "h?-blpxo:m:")) != -1) {
switch(o) {
case 'h': case '?': case '-': usage(); break;
case 'b': print_mode = MODE_BASE64; break;
case 'l': print_mode = MODE_LITERAL; break;
case 'p': print_mode = MODE_QPRINT; break;
case 'x': print_mode = MODE_HEX; break;
case 'o': outfile = optarg; break;
case 'm':
if(!sscanf(optarg, "%i", &line_max))
usage();
break;
}
}
dbfile = argv[optind];
if(!dbfile)
usage();
if(outfile) {
outfp = fopen(outfile, "w");
if(!outfp) {
perror(progname);
exit(1);
}
} else {
outfp = stdout;
}
t = tdb_open(dbfile, 0, 0, O_RDONLY, 0);
if(!t) {
/* fprintf(stderr, "%s: %s\n", progname, tdb_error(t)); */
/* oops, that doesn't make much sense, does it? tdb_error(NULL)? */
fprintf(stderr, "%s: cannot open TDB file %s\n", progname, dbfile);
exit(1);
}
do_header(outfp, dbfile, print_mode);
tdb_traverse(t, export_cb, 0);
tdb_close(t);
return 0;
}
More information about the samba-technical
mailing list