0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <stdio.h>
0015 #include <errno.h>
0016 #include <stdlib.h>
0017 #include <string.h>
0018 #include <ctype.h>
0019 #include <unistd.h>
0020 #include <signal.h>
0021 #include "exdb.h"
0022
0023 #define Yu EDB_PRIy(u)
0024
0025 #define PRINT 1
0026 static int mode;
0027
0028 typedef struct flagbit {
0029 int bit;
0030 char *name;
0031 } flagbit;
0032
0033 flagbit dbflags[] = {
0034 { EDB_REVERSEKEY, "reversekey" },
0035 { EDB_DUPSORT, "dupsort" },
0036 { EDB_INTEGERKEY, "integerkey" },
0037 { EDB_DUPFIXED, "dupfixed" },
0038 { EDB_INTEGERDUP, "integerdup" },
0039 { EDB_REVERSEDUP, "reversedup" },
0040 { 0, NULL }
0041 };
0042
0043 static volatile sig_atomic_t gotsig;
0044
0045 static void dumpsig( int sig )
0046 {
0047 gotsig=1;
0048 }
0049
0050 static const char hexc[] = "0123456789abcdef";
0051
0052 static void hex(unsigned char c)
0053 {
0054 putchar(hexc[c >> 4]);
0055 putchar(hexc[c & 0xf]);
0056 }
0057
0058 static void text(EDB_val *v)
0059 {
0060 unsigned char *c, *end;
0061
0062 putchar(' ');
0063 c = v->mv_data;
0064 end = c + v->mv_size;
0065 while (c < end) {
0066 if (isprint(*c)) {
0067 if (*c == '\\')
0068 putchar('\\');
0069 putchar(*c);
0070 } else {
0071 putchar('\\');
0072 hex(*c);
0073 }
0074 c++;
0075 }
0076 putchar('\n');
0077 }
0078
0079 static void byte(EDB_val *v)
0080 {
0081 unsigned char *c, *end;
0082
0083 putchar(' ');
0084 c = v->mv_data;
0085 end = c + v->mv_size;
0086 while (c < end) {
0087 hex(*c++);
0088 }
0089 putchar('\n');
0090 }
0091
0092
0093 static int dumpit(EDB_txn *txn, EDB_dbi dbi, char *name)
0094 {
0095 EDB_cursor *mc;
0096 EDB_stat ms;
0097 EDB_val key, data;
0098 EDB_envinfo info;
0099 unsigned int flags;
0100 int rc, i;
0101
0102 rc = edb_dbi_flags(txn, dbi, &flags);
0103 if (rc) return rc;
0104
0105 rc = edb_stat(txn, dbi, &ms);
0106 if (rc) return rc;
0107
0108 rc = edb_env_info(edb_txn_env(txn), &info);
0109 if (rc) return rc;
0110
0111 printf("VERSION=3\n");
0112 printf("format=%s\n", mode & PRINT ? "print" : "bytevalue");
0113 if (name)
0114 printf("database=%s\n", name);
0115 printf("type=btree\n");
0116 printf("mapsize=%"Yu"\n", info.me_mapsize);
0117 if (info.me_mapaddr)
0118 printf("mapaddr=%p\n", info.me_mapaddr);
0119 printf("maxreaders=%u\n", info.me_maxreaders);
0120
0121 if (flags & EDB_DUPSORT)
0122 printf("duplicates=1\n");
0123
0124 for (i=0; dbflags[i].bit; i++)
0125 if (flags & dbflags[i].bit)
0126 printf("%s=1\n", dbflags[i].name);
0127
0128 printf("db_pagesize=%d\n", ms.ms_psize);
0129 printf("HEADER=END\n");
0130
0131 rc = edb_cursor_open(txn, dbi, &mc);
0132 if (rc) return rc;
0133
0134 while ((rc = edb_cursor_get(mc, &key, &data, EDB_NEXT) == EDB_SUCCESS)) {
0135 if (gotsig) {
0136 rc = EINTR;
0137 break;
0138 }
0139 if (mode & PRINT) {
0140 text(&key);
0141 text(&data);
0142 } else {
0143 byte(&key);
0144 byte(&data);
0145 }
0146 }
0147 printf("DATA=END\n");
0148 if (rc == EDB_NOTFOUND)
0149 rc = EDB_SUCCESS;
0150
0151 return rc;
0152 }
0153
0154 static void usage(char *prog)
0155 {
0156 fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-v] [-a|-s subdb] dbpath\n", prog);
0157 exit(EXIT_FAILURE);
0158 }
0159
0160 int main(int argc, char *argv[])
0161 {
0162 int i, rc;
0163 EDB_env *env;
0164 EDB_txn *txn;
0165 EDB_dbi dbi;
0166 char *prog = argv[0];
0167 char *envname;
0168 char *subname = NULL;
0169 int alldbs = 0, envflags = 0, list = 0;
0170
0171 if (argc < 2) {
0172 usage(prog);
0173 }
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 while ((i = getopt(argc, argv, "af:lnps:vV")) != EOF) {
0185 switch(i) {
0186 case 'V':
0187 printf("%s\n", EDB_VERSION_STRING);
0188 exit(0);
0189 break;
0190 case 'l':
0191 list = 1;
0192 ;
0193 case 'a':
0194 if (subname)
0195 usage(prog);
0196 alldbs++;
0197 break;
0198 case 'f':
0199 if (freopen(optarg, "w", stdout) == NULL) {
0200 fprintf(stderr, "%s: %s: reopen: %s\n",
0201 prog, optarg, strerror(errno));
0202 exit(EXIT_FAILURE);
0203 }
0204 break;
0205 case 'n':
0206 envflags |= EDB_NOSUBDIR;
0207 break;
0208 case 'v':
0209 envflags |= EDB_PREVSNAPSHOT;
0210 break;
0211 case 'p':
0212 mode |= PRINT;
0213 break;
0214 case 's':
0215 if (alldbs)
0216 usage(prog);
0217 subname = optarg;
0218 break;
0219 default:
0220 usage(prog);
0221 }
0222 }
0223
0224 if (optind != argc - 1)
0225 usage(prog);
0226
0227 #ifdef SIGPIPE
0228 signal(SIGPIPE, dumpsig);
0229 #endif
0230 #ifdef SIGHUP
0231 signal(SIGHUP, dumpsig);
0232 #endif
0233 signal(SIGINT, dumpsig);
0234 signal(SIGTERM, dumpsig);
0235
0236 envname = argv[optind];
0237 rc = edb_env_create(&env);
0238 if (rc) {
0239 fprintf(stderr, "edb_env_create failed, error %d %s\n", rc, edb_strerror(rc));
0240 return EXIT_FAILURE;
0241 }
0242
0243 if (alldbs || subname) {
0244 edb_env_set_maxdbs(env, 2);
0245 }
0246
0247 rc = edb_env_open(env, envname, envflags | EDB_RDONLY, 0664);
0248 if (rc) {
0249 fprintf(stderr, "edb_env_open failed, error %d %s\n", rc, edb_strerror(rc));
0250 goto env_close;
0251 }
0252
0253 rc = edb_txn_begin(env, NULL, EDB_RDONLY, &txn);
0254 if (rc) {
0255 fprintf(stderr, "edb_txn_begin failed, error %d %s\n", rc, edb_strerror(rc));
0256 goto env_close;
0257 }
0258
0259 rc = edb_open(txn, subname, 0, &dbi);
0260 if (rc) {
0261 fprintf(stderr, "edb_open failed, error %d %s\n", rc, edb_strerror(rc));
0262 goto txn_abort;
0263 }
0264
0265 if (alldbs) {
0266 EDB_cursor *cursor;
0267 EDB_val key;
0268 int count = 0;
0269
0270 rc = edb_cursor_open(txn, dbi, &cursor);
0271 if (rc) {
0272 fprintf(stderr, "edb_cursor_open failed, error %d %s\n", rc, edb_strerror(rc));
0273 goto txn_abort;
0274 }
0275 while ((rc = edb_cursor_get(cursor, &key, NULL, EDB_NEXT_NODUP)) == 0) {
0276 char *str;
0277 EDB_dbi db2;
0278 if (memchr(key.mv_data, '\0', key.mv_size))
0279 continue;
0280 count++;
0281 str = malloc(key.mv_size+1);
0282 memcpy(str, key.mv_data, key.mv_size);
0283 str[key.mv_size] = '\0';
0284 rc = edb_open(txn, str, 0, &db2);
0285 if (rc == EDB_SUCCESS) {
0286 if (list) {
0287 printf("%s\n", str);
0288 list++;
0289 } else {
0290 rc = dumpit(txn, db2, str);
0291 if (rc)
0292 break;
0293 }
0294 edb_close(env, db2);
0295 }
0296 free(str);
0297 if (rc) continue;
0298 }
0299 edb_cursor_close(cursor);
0300 if (!count) {
0301 fprintf(stderr, "%s: %s does not contain multiple databases\n", prog, envname);
0302 rc = EDB_NOTFOUND;
0303 } else if (rc == EDB_NOTFOUND) {
0304 rc = EDB_SUCCESS;
0305 }
0306 } else {
0307 rc = dumpit(txn, dbi, subname);
0308 }
0309 if (rc && rc != EDB_NOTFOUND)
0310 fprintf(stderr, "%s: %s: %s\n", prog, envname, edb_strerror(rc));
0311
0312 edb_close(env, dbi);
0313 txn_abort:
0314 edb_txn_abort(txn);
0315 env_close:
0316 edb_env_close(env);
0317
0318 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
0319 }