Index: db.1 =================================================================== RCS file: /cvsroot/src/usr.bin/db/db.1,v retrieving revision 1.27 diff -u -r1.27 db.1 --- db.1 17 Feb 2012 11:43:24 -0000 1.27 +++ db.1 6 Jan 2013 02:38:50 -0000 @@ -51,7 +51,7 @@ .Op Fl T Ar visspec .Op Fl U Ar unvisitem .Op Fl X Ar extravis -.Ar type +.Op type .Ar dbfile .Op Ar key Op Ar \&.\&.\&. . @@ -62,7 +62,7 @@ .Op Fl f Ar infile .Op Fl T Ar visspec .Op Fl U Ar unvisitem -.Ar type +.Op type .Ar dbfile .Op Ar key Op Ar \&.\&.\&. . @@ -76,7 +76,7 @@ .Op Fl P Ar pagesize .Op Fl T Ar visspec .Op Fl U Ar unvisitem -.Ar type +.Op type .Ar dbfile .Op Ar key Ar value Op Ar \&.\&.\&. . @@ -122,15 +122,19 @@ .Ar insep ) . .El .Pp -There are two mandatory arguments: +There is one mandatory argument: +.Ar dbfile +is the database file to manipulate. +The database type can be specified on the command line, +by usint the .Ar type -is the database type; either +argument; either .Sq Sy btree or .Sq Sy hash , -and -.Ar dbfile -is the database file to manipulate. +options are possible. +If the database type is not specified, the type will be autodetected +from the database file itself. .Pp Options valid for all modes are: .Bl -tag -width Fl -offset indent Index: db.c =================================================================== RCS file: /cvsroot/src/usr.bin/db/db.c,v retrieving revision 1.26 diff -u -r1.26 db.c --- db.c 17 Feb 2012 11:37:33 -0000 1.26 +++ db.c 6 Jan 2013 02:38:50 -0000 @@ -71,6 +71,14 @@ F_DECODE_VAL = 1<<26, } flags_t; +#ifndef __dead +#define __dead __dead2 +#endif + +#ifdef __FreeBSD__ +int strsvisx(char *, const char *, size_t, int, const char *); +#endif + static void db_print(DBT *, DBT *); static int db_dump(void); static int db_del(char *); @@ -83,6 +91,7 @@ static void parse_encode_decode_arg(const char *, int); static int parse_encode_option(char **); __dead static void usage(void); +static int autodetect(char */*file*/, char */*type*/, size_t /*typesize*/); static flags_t flags = 0; static DB *db; @@ -106,6 +115,7 @@ HASHINFO hashinfo; FILE *infp; const char *infile, *fieldsep; + char autotype[16]; char *p, *key, *val; int ch, rv; long lval; @@ -249,13 +259,21 @@ argc -= optind; argv += optind; - /* validate arguments */ - if (argc < 2) - usage(); - oi.type = argv[0]; - oi.file = argv[1]; - argc -= 2; - argv += 2; + /* validate arguments */ + if (argc < 2) { + /* auto-detect the type of database */ + if (!autodetect(oi.file = argv[0], autotype, sizeof(autotype))) { + usage(); + } + oi.type = autotype; + argc -= 1; + argv += 1; + } else { + oi.type = argv[0]; + oi.file = argv[1]; + argc -= 2; + argv += 2; + } if (flags & F_WRITE) { if (flags & (F_SHOW_KEY | F_SHOW_VALUE | F_DELETE)) @@ -752,3 +770,40 @@ ); exit(1); } + +#include + +typedef struct dbtype_map_t { + uint32_t magic; + const char *type; +} dbtype_map_t; + +static dbtype_map_t dbtypes[] = { + { BTREEMAGIC, "btree" }, + { HASHMAGIC, "hash" }, + { 0, NULL } +}; + +static int +autodetect(char *file, char *type, size_t typesize) +{ + dbtype_map_t *map; + uint32_t magic; + FILE *fp; + int found; + + if ((fp = fopen(file, "r")) == NULL) { + return 0; + } + found = 0; + if (read(fileno(fp), &magic, sizeof(magic)) == sizeof(magic)) { + for (map = dbtypes ; !found && map->type ; map++) { + if (magic == map->magic || magic == htonl(map->magic)) { + snprintf(type, typesize, map->type); + found = 1; + } + } + } + fclose(fp); + return found; +}