📄 db_load.c
字号:
case '1': \ if ((ret = dbp->set_flags(dbp, flag)) != 0) { \ dbp->err(dbp, ret, "%s: set_flags: %s", \ G(progname), name); \ goto err; \ } \ break; \ case '0': \ break; \ default: \ db_load_badnum(dbenv); \ goto err; \ } \ continue; \ }#define NUMBER(name, value, keyword, func, t) \ if (strcmp(name, keyword) == 0) { \ if ((ret = __db_getlong(dbenv, \ NULL, value, 0, LONG_MAX, &val)) != 0 || \ (ret = dbp->func(dbp, (t)val)) != 0) \ goto nameerr; \ continue; \ }#define STRING(name, value, keyword, func) \ if (strcmp(name, keyword) == 0) { \ if ((ret = dbp->func(dbp, value[0])) != 0) \ goto nameerr; \ continue; \ }/* * The code to check a command-line or input header argument against a list * of configuration options. It's #defined because it's used in two places * and the two places have gotten out of sync more than once. */#define CONFIGURATION_LIST_COMPARE \ NUMBER(name, value, "bt_minkey", set_bt_minkey, u_int32_t); \ FLAG(name, value, "chksum", DB_CHKSUM); \ NUMBER(name, value, "db_lorder", set_lorder, int); \ NUMBER(name, value, "db_pagesize", set_pagesize, u_int32_t); \ FLAG(name, value, "duplicates", DB_DUP); \ FLAG(name, value, "dupsort", DB_DUPSORT); \ NUMBER(name, value, "extentsize", set_q_extentsize, u_int32_t); \ NUMBER(name, value, "h_ffactor", set_h_ffactor, u_int32_t); \ NUMBER(name, value, "h_nelem", set_h_nelem, u_int32_t); \ NUMBER(name, value, "re_len", set_re_len, u_int32_t); \ STRING(name, value, "re_pad", set_re_pad); \ FLAG(name, value, "recnum", DB_RECNUM); \ FLAG(name, value, "renumber", DB_RENUMBER)/* * configure -- * Handle command-line configuration options. */intdb_load_configure(dbenv, dbp, clp, subdbp, keysp) DB_ENV *dbenv; DB *dbp; char **clp, **subdbp; int *keysp;{ long val; int ret, savech; char *name, *value; for (; (name = *clp) != NULL; *--value = savech, ++clp) { if ((value = strchr(name, '=')) == NULL) { dbp->errx(dbp, "command-line configuration uses name=value format"); return (1); } savech = *value; *value++ = '\0'; if (strcmp(name, "database") == 0 || strcmp(name, "subdatabase") == 0) { if (*subdbp != NULL) free(*subdbp); if ((*subdbp = strdup(value)) == NULL) { dbp->err(dbp, ENOMEM, NULL); return (1); } continue; } if (strcmp(name, "keys") == 0) { if (strcmp(value, "1") == 0) *keysp = 1; else if (strcmp(value, "0") == 0) *keysp = 0; else { db_load_badnum(dbenv); return (1); } continue; } CONFIGURATION_LIST_COMPARE; dbp->errx(dbp, "unknown command-line configuration keyword \"%s\"", name); return (1); } return (0);nameerr: dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);err: return (1);}/* * rheader -- * Read the header message. */intdb_load_rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp) DB_ENV *dbenv; DB *dbp; DBTYPE *dbtypep; char **subdbp; int *checkprintp, *keysp;{ size_t buflen, linelen, start; long val; int ch, first, hdr, ret; char *buf, *name, *p, *value; *dbtypep = DB_UNKNOWN; *checkprintp = 0; name = NULL; /* * We start with a smallish buffer; most headers are small. * We may need to realloc it for a large subdatabase name. */ buflen = 4096; if (G(hdrbuf) == NULL) { hdr = 0; if ((buf = malloc(buflen)) == NULL) goto memerr; G(hdrbuf) = buf; G(origline) = G(lineno); } else { hdr = 1; buf = G(hdrbuf); G(lineno) = G(origline); } start = 0; for (first = 1;; first = 0) { ++G(lineno); /* Read a line, which may be of arbitrary length, into buf. */ linelen = 0; buf = &G(hdrbuf)[start]; if (hdr == 0) { for (;;) { if ((ch = getchar()) == EOF) { if (!first || ferror(stdin)) goto badfmt; G(endofile) = 1; break; } /* * If the buffer is too small, double it. */ if (linelen + start == buflen) { G(hdrbuf) = realloc(G(hdrbuf), buflen *= 2); if (G(hdrbuf) == NULL) goto memerr; buf = &G(hdrbuf)[start]; } if (ch == '\n') break; buf[linelen++] = ch; } if (G(endofile) == 1) break; buf[linelen++] = '\0'; } else linelen = strlen(buf) + 1; start += linelen; if (name != NULL) { free(name); name = NULL; } /* If we don't see the expected information, it's an error. */ if ((name = strdup(buf)) == NULL) goto memerr; if ((p = strchr(name, '=')) == NULL) goto badfmt; *p++ = '\0'; value = p--; if (name[0] == '\0') goto badfmt; /* * The only values that may be zero-length are database names. * In the original Berkeley DB code it was possible to create * zero-length database names, and the db_load code was then * changed to allow such databases to be be dumped and loaded. * [#8204] */ if (strcmp(name, "database") == 0 || strcmp(name, "subdatabase") == 0) { if ((ret = db_load_convprintable(dbenv, value, subdbp)) != 0) { dbp->err(dbp, ret, "error reading db name"); goto err; } continue; } /* No other values may be zero-length. */ if (value[0] == '\0') goto badfmt; if (strcmp(name, "HEADER") == 0) break; if (strcmp(name, "VERSION") == 0) { /* * Version 1 didn't have a "VERSION" header line. We * only support versions 1, 2, and 3 of the dump format. */ G(version) = atoi(value); if (G(version) > 3) { dbp->errx(dbp, "line %lu: VERSION %d is unsupported", G(lineno), G(version)); goto err; } continue; } if (strcmp(name, "format") == 0) { if (strcmp(value, "bytevalue") == 0) { *checkprintp = 0; continue; } if (strcmp(value, "print") == 0) { *checkprintp = 1; continue; } goto badfmt; } if (strcmp(name, "type") == 0) { if (strcmp(value, "btree") == 0) { *dbtypep = DB_BTREE; continue; } if (strcmp(value, "hash") == 0) { *dbtypep = DB_HASH; continue; } if (strcmp(value, "recno") == 0) { *dbtypep = DB_RECNO; continue; } if (strcmp(value, "queue") == 0) { *dbtypep = DB_QUEUE; continue; } dbp->errx(dbp, "line %lu: unknown type", G(lineno)); goto err; } if (strcmp(name, "keys") == 0) { if (strcmp(value, "1") == 0) *keysp = 1; else if (strcmp(value, "0") == 0) *keysp = 0; else { db_load_badnum(dbenv); goto err; } continue; } CONFIGURATION_LIST_COMPARE; dbp->errx(dbp, "unknown input-file header configuration keyword \"%s\"", name); goto err; } ret = 0; if (0) {nameerr: dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value); ret = 1; } if (0) {badfmt: dbp->errx(dbp, "line %lu: unexpected format", G(lineno)); ret = 1; } if (0) {memerr: dbp->errx(dbp, "unable to allocate memory");err: ret = 1; } if (name != NULL) free(name); return (ret);}/* * Macro to convert a pair of hex bytes to a decimal value. * * !!! * Note that this macro is side-effect safe. This was done deliberately, * callers depend on it. */#define DIGITIZE(store, v1, v2) { \ char _v1, _v2; \ _v1 = (v1); \ _v2 = (v2); \ if ((_v1) > 'f' || (_v2) > 'f') \ return (db_load_badend(dbenv)); \ (store) = \ ((_v1) == '0' ? 0 : \ ((_v1) == '1' ? 1 : \ ((_v1) == '2' ? 2 : \ ((_v1) == '3' ? 3 : \ ((_v1) == '4' ? 4 : \ ((_v1) == '5' ? 5 : \ ((_v1) == '6' ? 6 : \ ((_v1) == '7' ? 7 : \ ((_v1) == '8' ? 8 : \ ((_v1) == '9' ? 9 : \ ((_v1) == 'a' ? 10 : \ ((_v1) == 'b' ? 11 : \ ((_v1) == 'c' ? 12 : \ ((_v1) == 'd' ? 13 : \ ((_v1) == 'e' ? 14 : 15))))))))))))))) << 4 | \ ((_v2) == '0' ? 0 : \ ((_v2) == '1' ? 1 : \ ((_v2) == '2' ? 2 : \ ((_v2) == '3' ? 3 : \ ((_v2) == '4' ? 4 : \ ((_v2) == '5' ? 5 : \ ((_v2) == '6' ? 6 : \ ((_v2) == '7' ? 7 : \ ((_v2) == '8' ? 8 : \ ((_v2) == '9' ? 9 : \ ((_v2) == 'a' ? 10 : \ ((_v2) == 'b' ? 11 : \ ((_v2) == 'c' ? 12 : \ ((_v2) == 'd' ? 13 : \ ((_v2) == 'e' ? 14 : 15))))))))))))))); \}/* * convprintable -- * Convert a printable-encoded string into a newly allocated string. * * In an ideal world, this would probably share code with dbt_rprint, but * that's set up to read character-by-character (to avoid large memory * allocations that aren't likely to be a problem here), and this has fewer * special cases to deal with. * * Note that despite the printable encoding, the char * interface to this * function (which is, not coincidentally, also used for database naming) * means that outstr cannot contain any nuls. */intdb_load_convprintable(dbenv, instr, outstrp) DB_ENV *dbenv; char *instr, **outstrp;{ char *outstr; /* * Just malloc a string big enough for the whole input string; * the output string will be smaller (or of equal length). * * Note that we may be passed a zero-length string and need to * be able to duplicate it. */ if ((outstr = malloc(strlen(instr) + 1)) == NULL) return (ENOMEM); *outstrp = outstr; for ( ; *instr != '\0'; instr++) if (*instr == '\\') { if (*++instr == '\\') { *outstr++ = '\\'; continue; } DIGITIZE(*outstr++, *instr, *++instr); } else *outstr++ = *instr; *outstr = '\0'; return (0);}/* * dbt_rprint -- * Read a printable line into a DBT structure. */intdb_load_dbt_rprint(dbenv, dbtp) DB_ENV *dbenv; DBT *dbtp;{ u_int32_t len; u_int8_t *p; int c1, c2, escape, first; char buf[32]; ++G(lineno); first = 1; escape = 0; for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) { if (c1 == EOF) { if (len == 0) { G(endofile) = G(endodata) = 1; return (0); } return (db_load_badend(dbenv)); } if (first) { first = 0; if (G(version) > 1) { if (c1 != ' ') { buf[0] = c1; if (fgets(buf + 1, sizeof(buf) - 1, stdin) == NULL || strcmp(buf, "DATA=END\n") != 0) return (db_load_badend(dbenv)); G(endodata) = 1; return (0); } continue; } } if (escape) { if (c1 != '\\') { if ((c2 = getchar()) == EOF) return (db_load_badend(dbenv)); DIGITIZE(c1, c1, c2); } escape = 0; } else if (c1 == '\\') { escape = 1; continue; } if (len >= dbtp->ulen - 10) { dbtp->ulen *= 2; if ((dbtp->data = realloc(dbtp->data, dbtp->ulen)) == NULL) { dbenv->err(dbenv, ENOMEM, NULL); return (1); } p = (u_int8_t *)dbtp->data + len; } ++len; *p++ = c1; } dbtp->size = len; return (0);}/* * dbt_rdump -- * Read a byte dump line into a DBT structure. */intdb_load_dbt_rdump(dbenv, dbtp) DB_ENV *dbenv; DBT *dbtp;{ u_int32_t len; u_int8_t *p; int c1, c2, first; char buf[32]; ++G(lineno); first = 1; for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) { if (c1 == EOF) { if (len == 0) { G(endofile) = G(endodata) = 1; return (0); } return (db_load_badend(dbenv)); } if (first) { first = 0; if (G(version) > 1) { if (c1 != ' ') { buf[0] = c1; if (fgets(buf + 1, sizeof(buf) - 1, stdin) == NULL || strcmp(buf, "DATA=END\n") != 0) return (db_load_badend(dbenv)); G(endodata) = 1; return (0); } continue; } } if ((c2 = getchar()) == EOF) return (db_load_badend(dbenv)); if (len >= dbtp->ulen - 10) { dbtp->ulen *= 2; if ((dbtp->data = realloc(dbtp->data, dbtp->ulen)) == NULL) { dbenv->err(dbenv, ENOMEM, NULL); return (1); } p = (u_int8_t *)dbtp->data + len; } ++len; DIGITIZE(*p++, c1, c2); } dbtp->size = len; return (0);}/* * dbt_rrecno -- * Read a record number dump line into a DBT structure. */intdb_load_dbt_rrecno(dbenv, dbtp, ishex) DB_ENV *dbenv; DBT *dbtp; int ishex;{ char buf[32], *p, *q; u_long recno; ++G(lineno); if (fgets(buf, sizeof(buf), stdin) == NULL) { G(endofile) = G(endodata) = 1; return (0); } if (strcmp(buf, "DATA=END\n") == 0) { G(endodata) = 1; return (0); } if (buf[0] != ' ') goto err; /* * If we're expecting a hex key, do an in-place conversion * of hex to straight ASCII before calling __db_getulong(). */ if (ishex) { for (p = q = buf + 1; *q != '\0' && *q != '\n';) { /* * 0-9 in hex are 0x30-0x39, so this is easy. * We should alternate between 3's and [0-9], and * if the [0-9] are something unexpected, * __db_getulong will fail, so we only need to catch * end-of-string conditions. */ if (*q++ != '3') goto err; if (*q == '\n' || *q == '\0') goto err; *p++ = *q++; } *p = '\0'; } if (__db_getulong(dbenv, G(progname), buf + 1, 0, 0, &recno)) goto err; *((db_recno_t *)dbtp->data) = recno; dbtp->size = sizeof(db_recno_t); return (0);err: return (db_load_badend(dbenv));}intdb_load_dbt_to_recno(dbenv, dbt, recnop) DB_ENV *dbenv; DBT *dbt; db_recno_t *recnop;{ char buf[32]; /* Large enough for 2^64. */ memcpy(buf, dbt->data, dbt->size); buf[dbt->size] = '\0'; return (__db_getulong(dbenv, G(progname), buf, 0, 0, (u_long *)recnop));}/* * badnum -- * Display the bad number message. */voiddb_load_badnum(dbenv) DB_ENV *dbenv;{ dbenv->errx(dbenv, "boolean name=value pairs require a value of 0 or 1");}/* * badend -- * Display the bad end to input message. */intdb_load_badend(dbenv) DB_ENV *dbenv;{ dbenv->errx(dbenv, "unexpected end of input data or key/data pair"); return (1);}/* * usage -- * Display the usage message. */intdb_load_usage(){ (void)fprintf(stderr, "usage: %s %s\n\t%s\n", progname, "[-nTV] [-c name=value] [-f file]", "[-h home] [-P password] [-t btree | hash | recno | queue] db_file"); (void)fprintf(stderr, "usage: %s %s\n", progname, "-r lsn | fileid [-h home] [-P password] db_file"); return (EXIT_FAILURE);}intdb_load_version_check(){ int v_major, v_minor, v_patch; /* Make sure we're loaded with the right version of the DB library. */ (void)db_version(&v_major, &v_minor, &v_patch); if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) { fprintf(stderr, "%s: version %d.%d doesn't match library version %d.%d\n", progname, DB_VERSION_MAJOR, DB_VERSION_MINOR, v_major, v_minor); return (EXIT_FAILURE); } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -