Esempio n. 1
0
/*
 * DbRecord_field --
 *	Fill in an individual field of the DbRecord.
 */
static int
DbRecord_field(
    DbRecord *recordp, u_int field, void *addr, datatype type)
{
	size_t len;
	char number_buf[20];

	/*
	 * The offset table is 0-based, the field numbers are 1-based.
	 * Correct.
	 */
	--field;

	switch (type) {
	case NOTSET:
		/* NOTREACHED */
		abort();
		break;
	case STRING:
		*((u_char **)addr) = recordp->record + recordp->offset[field];
		recordp->record[recordp->offset[field] +
		    OFFSET_LEN(recordp->offset, field)] = '\0';
		break;
	case DOUBLE:
	case UNSIGNED_LONG:
		/* This shouldn't be possible -- 2^32 is only 10 digits. */
		len = OFFSET_LEN(recordp->offset, field);
		if (len > sizeof(number_buf) - 1) {
			dbenv->errx(dbenv,
    "record %lu field %lu: numeric field is %lu bytes and too large to copy",
			    recordp->recno, field, (u_long)len);
			return (1);
		}
		memcpy(number_buf,
		    recordp->record + recordp->offset[field], len);
		number_buf[len] = '\0';

		if (type == DOUBLE) {
			if (len == 0)
				*(double *)addr = 0;
			else if (strtod_err(number_buf, (double *)addr) != 0)
				goto fmt_err;
		} else
			if (len == 0)
				*(u_long *)addr = 0;
			else if (strtoul_err(number_buf, (u_long *)addr) != 0) {
fmt_err:			dbenv->errx(dbenv,
				    "record %lu: numeric field %u error: %s",
				    recordp->recno, field, number_buf);
				return (1);
			}
		break;
	}
	return (0);
}
Esempio n. 2
0
int
main(int argc, char *argv[])
{
	input_fmt ifmt;
	u_long version;
	int ch, ret, t_ret;
	char *home;

	/* Initialize globals. */
	dbenv = NULL;
	db = NULL;
	if ((progname = strrchr(argv[0], '/')) == NULL)
		progname = argv[0];
	else
		++progname;
	verbose = 0;
	ffp = NULL;

	/* Initialize arguments. */
	home = NULL;
	ifmt = FORMAT_NL;
	version = 1;

	/* Process arguments. */
	while ((ch = getopt(argc, argv, "F:f:h:V:v")) != EOF)
		switch (ch) {
		case 'f':		/* Required argument */
			if ((ffp = freopen(optarg, "r", stdin)) == NULL) {
				fprintf(stderr,
				    "%s: %s\n", optarg, db_strerror(errno));
				return (EXIT_FAILURE);
			}
			break;
		case 'F':
			if (strcasecmp(optarg, "excel") == 0) {
				ifmt = FORMAT_EXCEL;
				break;
			}
			return (usage());
		case 'h':
			home = optarg;
			break;
		case 'V':
			if (strtoul_err(optarg, &version))
				return (EXIT_FAILURE);
			break;
		case 'v':
			++verbose;
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= optind;
	argv += optind;

	if (*argv != NULL || ffp == NULL)
		return (usage());

	/*
	 * The home directory may not exist -- try and create it.  We don't
	 * bother to distinguish between failure to create it and it already
	 * existing, as the database environment open will fail if we aren't
	 * successful.
	 */
	if (home == NULL)
		home = getenv("DB_HOME");
	if (home != NULL)
		(void)mkdir(home, S_IRWXU);

	/* Create or join the database environment. */
	if (csv_env_open(home, 0) != 0)
		return (EXIT_FAILURE);

	/* Load records into the database. */
	ret = input_load(ifmt, version);

	/* Close the database environment. */
	if ((t_ret = csv_env_close()) != 0 && ret == 0)
		ret = t_ret;

	return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
Esempio n. 3
0
/*
 * DbRecord_search_field --
 *	Search, looking for a record by field.
 */
static int
DbRecord_search_field(DbField *f, char *value, OPERATOR op)
{
#ifdef HAVE_WILDCARD_SUPPORT
	regex_t preq;
#endif
	DBC *dbc;
	DbRecord record;
	DBT key, data, pkey;
	double value_double;
	u_long value_ulong;
	u_int32_t cursor_flags;
	int ret, t_ret;
	int (*cmp)(void *, void *, OPERATOR);
	void *faddr, *valuep;

	dbc = NULL;
	memset(&key, 0, sizeof(key));
	memset(&pkey, 0, sizeof(pkey));
	memset(&data, 0, sizeof(data));

	/*
	 * Initialize the comparison function, crack the value.  Wild cards
	 * are always strings, otherwise we follow the field type.
	 */
	if (op == WC || op == NWC) {
#ifdef HAVE_WILDCARD_SUPPORT
		if (f->type != STRING) {
			dbenv->errx(dbenv,
		    "wildcard operator only supported for string fields");
			return (1);
		}
		if (regcomp(&preq, value, 0) != 0) {
			dbenv->errx(dbenv, "regcomp of pattern failed");
			return (1);
		}
		valuep = &preq;
		cmp = field_cmp_re;
#else
		dbenv->errx(dbenv,
		    "wildcard operators not supported in this build");
		return (1);
#endif
	} else
		switch (f->type) {
		case DOUBLE:
			if (strtod_err(value, &value_double) != 0)
				return (1);
			cmp = field_cmp_double;
			valuep = &value_double;
			key.size = sizeof(double);
			break;
		case STRING:
			valuep = value;
			cmp = field_cmp_string;
			key.size = (u_int32_t)strlen(value);
			break;
		case UNSIGNED_LONG:
			if (strtoul_err(value, &value_ulong) != 0)
				return (1);
			cmp = field_cmp_ulong;
			valuep = &value_ulong;
			key.size = sizeof(u_long);
			break;
		default:
		case NOTSET:
			abort();
			/* NOTREACHED */
		}

	/*
	 * Retrieve the first record that interests us.  The range depends on
	 * the operator:
	 *
	 *	~		beginning to end
	 *	!=		beginning to end
	 *	<		beginning to first match
	 *	<=		beginning to last match
	 *	=		first match to last match
	 *	>		record after last match to end
	 *	>=		first match to end
	 *
	 * If we have a secondary, set a cursor in the secondary, else set the
	 * cursor to the beginning of the primary.
	 *
	 * XXX
	 * If the wildcard string has a leading non-magic character we should
	 * be able to do a range search instead of a full-database search.
	 *
	 * Step through records to the first non-match or to the end of the
	 * database, depending on the operation.  If the comparison function
	 * returns success for a key/data pair, print the pair.
	 */
	if (f->secondary == NULL || op == NEQ || op == WC || op == NWC) {
		if ((ret = db->cursor(db, NULL, &dbc, 0)) != 0)
			goto err;
		while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
			if ((ret = DbRecord_init(&key, &data, &record)) != 0)
				break;
			faddr = (u_int8_t *)&record + f->offset;
			if (cmp(faddr, valuep, op))
				DbRecord_print(&record, NULL);
			else
				if (op == EQ || op == LT || op == LTEQ)
					break;
		}
	} else {
		if ((ret =
		    f->secondary->cursor(f->secondary, NULL, &dbc, 0)) != 0)
			goto err;
		key.data = valuep;
		cursor_flags = op == LT || op == LTEQ ? DB_FIRST : DB_SET_RANGE;
		if ((ret =
		    dbc->c_pget(dbc, &key, &pkey, &data, cursor_flags)) != 0)
			goto done;
		if (op == GT) {
			while ((ret = dbc->c_pget(
			    dbc, &key, &pkey, &data, DB_NEXT)) == 0) {
				if ((ret =
				    DbRecord_init(&pkey, &data, &record)) != 0)
					break;
				faddr = (u_int8_t *)&record + f->offset;
				if (cmp(faddr, valuep, op) != 0)
					break;
			}
			if (ret != 0)
				goto done;
		}
		do {
			if ((ret = DbRecord_init(&pkey, &data, &record)) != 0)
				break;
			faddr = (u_int8_t *)&record + f->offset;
			if (cmp(faddr, valuep, op))
				DbRecord_print(&record, NULL);
			else
				if (op == EQ || op == LT || op == LTEQ)
					break;
		} while ((ret =
		    dbc->c_pget(dbc, &key, &pkey, &data, DB_NEXT)) == 0);
	}

done:	if (ret == DB_NOTFOUND)
		ret = 0;

err:	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
		ret = t_ret;

#ifdef HAVE_WILDCARD_SUPPORT
	if (op == WC || op == NWC)
		regfree(&preq);
#endif

	return (ret);
}
Esempio n. 4
0
/*
 * DbRecord_search_recno --
 *	Search, looking for a record by record number.
 */
static int
DbRecord_search_recno(char *value, OPERATOR op)
{
	DBC *dbc;
	DbRecord record;
	DBT key, data;
	u_int32_t recno;
	u_long recno_ulong;
	int ret;

	/*
	 * XXX
	 * This code assumes a record number (typed as u_int32_t) is the same
	 * size as an unsigned long, and there's no reason to believe that.
	 */
	if (strtoul_err(value, &recno_ulong) != 0)
		return (1);

	memset(&key, 0, sizeof(key));
	memset(&data, 0, sizeof(data));
	key.data = &recno;
	key.size = sizeof(recno);

	if ((ret = db->cursor(db, NULL, &dbc, 0)) != 0)
		return (ret);

	/*
	 * Retrieve the first record that interests us.  The range depends on
	 * the operator:
	 *
	 *	~		error
	 *	!=		beginning to end
	 *	<		beginning to first match
	 *	<=		beginning to last match
	 *	=		first match to last match
	 *	>		record after last match to end
	 *	>=		first match to end
	 */
	if (op == LT || op == LTEQ || op == NEQ || op == WC || op == NWC)
		recno = 1;
	else if (op == WC || op == NWC) {
		dbenv->errx(dbenv,
		    "wildcard operator only supported for string fields");
		return (1);
	} else {
		recno = recno_ulong;
		if (op == GT)
			++recno;
	}
	if ((ret = dbc->c_get(dbc, &key, &data, DB_SET)) != 0)
		goto err;

	for (;;) {
		if ((ret = DbRecord_init(&key, &data, &record)) != 0)
			break;
		if (field_cmp_ulong(&record.recno, &recno_ulong, op))
			DbRecord_print(&record, NULL);
		else
			if (op == LT || op == LTEQ || op == EQ)
				break;
		if ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) != 0)
			break;
	}

err:	return (ret == DB_NOTFOUND ? 0 : ret);
}