/* * Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_IDSTR(id, "@(#)$Id: t-idb-0.c,v 1.59 2007/06/18 04:42:31 ca Exp $") #include "sm/io.h" #include "sm/mta.h" #include "sm/cstr.h" #include "sm/cdb.h" #include "sm/ibdb.h" #include "sm/qmgr.h" #include "sm/memops.h" #include "sm/bhtable.h" #include "sm/sysexits.h" #include "sm/test.h" #include "ibdb.h" #include /* ** Test program to write and read IBDB. ** Uses wribdb.c to write IBDB. */ #define FNAME "ibd" #define IBDBSIZE 8192 #define INIT_SEQ 1 static int init_seq = INIT_SEQ; static uint n_trunc = 128; static int Verbose = 0; /* ** ToDo: ** - more consistency checks for read data. ** - cleanup files. */ #include "../checks/wribdb.c" /* ** TESTIDBR -- read INCEDB records ** ** Parameters: ** base_dir -- name of base directory (can be NULL) ** iter -- number of iterations (transactions) ** maxs -- maximum size of an INCEDB file ** ** Returns: ** usual sm_error code. */ static sm_ret_T testidbr(const char *base_dir, int iter, int maxs, uint flags) { int i, j, nrcpts, status; ibdbr_ctx_P ibdbr_ctx; ibdb_ta_P ibdb_ta; ibdb_rcpt_P rcpt; ibdb_hdrmod_P ibdb_hdrmod; sessta_id_T ta_id; id_count_T id_count; sm_str_P str; sm_ret_T ret; uint32_t first, last; char hdr[SM_MAXHDRLEN]; ibdb_ta = NULL; rcpt = NULL; str = NULL; ibdbr_ctx = NULL; last = 1; ret = ibdbf_get_seq(base_dir, FNAME, IBDB_OFL_WRITE, &first, &last); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return ret; str = sm_str_new(NULL, 256, 256); SM_TEST(str != NULL); if (str == NULL) goto end; if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATE) && !WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATED)) { int r; struct stat sb; off_t size; const char *name; crt_ibdb_path(str, IBDB_WR_DIR, FNAME, last); name = (const char *) sm_str_getdata(str); r = stat(name, &sb); if (Verbose > 1) sm_io_fprintf(smioerr, "truncating=%s, r=%d, size=%ld\n", name, r, sb.st_size); SM_TEST(0 == r); if (0 == r && (size = sb.st_size) > 0) { if (size > n_trunc) size -= n_trunc; else --size; r = truncate(name, size); } flags |= WRIBDB_FL_TRUNCATED; } ret = ibdbr_open(base_dir, FNAME, SM_IO_RDONLY, init_seq, maxs, IBDB_OFL_WRITE, &ibdbr_ctx); if (sm_is_err(ret) && sm_error_value(ret) == ENOENT) { ret = ibdbr_open(base_dir, FNAME, SM_IO_RDONLY, first, maxs, IBDB_OFL_WRITE, &ibdbr_ctx); SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return ret; } SM_TEST(ret == SM_SUCCESS); if (ret != SM_SUCCESS) return ret; ibdb_ta = (ibdb_ta_P) sm_zalloc(sizeof(*ibdb_ta)); SM_TEST(ibdb_ta != NULL); if (ibdb_ta == NULL) goto end; ibdb_ta->ibt_ta_id = ta_id; ibdb_ta->ibt_mail_pa = sm_str_new(NULL, 256, 256); SM_TEST(ibdb_ta->ibt_mail_pa != NULL); if (ibdb_ta->ibt_mail_pa == NULL) goto end; ibdb_hdrmod = (ibdb_hdrmod_P) sm_zalloc(sizeof(*ibdb_hdrmod)); SM_TEST(ibdb_hdrmod != NULL); if (ibdb_hdrmod == NULL) goto end; ibdb_hdrmod->ibh_ta_id = ta_id; rcpt = (ibdb_rcpt_P) sm_zalloc(sizeof(*rcpt)); SM_TEST(rcpt != NULL); if (rcpt == NULL) goto end; rcpt->ibr_ta_id = ta_id; rcpt->ibr_pa = sm_str_new(NULL, 256, 256); SM_TEST(rcpt->ibr_pa != NULL); if (rcpt->ibr_pa == NULL) goto end; id_count = 0; if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_1OPENTA)) { i = INT_MAX; j = INT_MAX > 2; sm_str_clr(str); ret = sm_strprintf(str, "rcpt-%d-%d@other.Rcpt", i, j); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status); SM_TEST_E(ret == RT_IBDB_RCPT); SM_TEST_E(sm_memeq(sm_str_getdata(str), sm_str_getdata(rcpt->ibr_pa), sm_str_getlen(rcpt->ibr_pa))); SM_TEST_E(rcpt->ibr_idx == (rcpt_idx_T) j); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status); SM_TEST_E(ret == RT_IBDB_TA); SM_CSTR_FREE(ibdb_ta->ibt_cdb_id); } for (i = 0; i < iter; i++) { id_count++; nrcpts = (rcpts_per_ta > 0) ? rcpts_per_ta : (i % 5) + 1; for (j = 0; j < nrcpts; j++) { sm_str_clr(str); ret = sm_strprintf(str, "rcpt-%d-%d@other.Rcpt", i, j); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod , &status); SM_TEST(ret == RT_IBDB_RCPT); if (sm_is_err(ret)) goto end; SM_TEST(sm_memeq(sm_str_getdata(str), sm_str_getdata(rcpt->ibr_pa), sm_str_getlen(rcpt->ibr_pa))); SM_TEST(rcpt->ibr_idx == (rcpt_idx_T) j); } ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status); if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_LONG)) { SM_TEST_E(RT_IBDB_HDRMOD == ret); SM_TEST(SM_HM_TYPE_PREPEND == ibdb_hdrmod->ibh_type); SM_TEST_E(NULL != long_str); j = snprintf(long_str, long_str_len, "HeaderPreLong: prepend ta=%s i=%d", ta_id, i); for (; j < long_str_len - 4; j++) long_str[j] = '0' + (j % 10); long_str[long_str_len - 4] ='\r'; long_str[long_str_len - 3] ='\n'; long_str[long_str_len - 2] ='\0'; SM_TEST(sm_memeq(long_str, sm_cstr_data(ibdb_hdrmod->ibh_hdr), sm_cstr_getlen(ibdb_hdrmod->ibh_hdr))); SM_CSTR_FREE(ibdb_hdrmod->ibh_hdr); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod , &status); } if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_HDR_PRE)) { SM_TEST(RT_IBDB_HDRMOD == ret); if (sm_is_err(ret)) break; SM_TEST(SM_HM_TYPE_PREPEND == ibdb_hdrmod->ibh_type); ret = snprintf(hdr, sizeof(hdr), "HeaderPre: prepend ta=%s i=%d\r\n", ta_id, i); SM_TEST(sm_memeq(hdr, sm_cstr_data(ibdb_hdrmod->ibh_hdr), sm_cstr_getlen(ibdb_hdrmod->ibh_hdr))); SM_CSTR_FREE(ibdb_hdrmod->ibh_hdr); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod , &status); } if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_HDR_REM)) { SM_TEST(RT_IBDB_HDRMOD == ret); SM_TEST(SM_HM_TYPE_REMOVE == ibdb_hdrmod->ibh_type); SM_TEST(2 == ibdb_hdrmod->ibh_pos); SM_TEST(NULL == ibdb_hdrmod->ibh_hdr); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod , &status); } if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_HDR_APP)) { SM_TEST(RT_IBDB_HDRMOD == ret); SM_TEST(SM_HM_TYPE_APPEND == ibdb_hdrmod->ibh_type); ret = snprintf(hdr, sizeof(hdr), "HeaderApp: append ta=%s i=%d\r\n", ta_id, i); SM_TEST(sm_memeq(hdr, sm_cstr_data(ibdb_hdrmod->ibh_hdr), sm_cstr_getlen(ibdb_hdrmod->ibh_hdr))); SM_CSTR_FREE(ibdb_hdrmod->ibh_hdr); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod , &status); } SM_TEST(ret == RT_IBDB_TA); if (sm_is_err(ret)) break; /* check ta content?? */ SM_CSTR_FREE(ibdb_ta->ibt_cdb_id); for (j = 0; j < nrcpts; j++) { sm_str_clr(str); ret = sm_strprintf(str, "rcpt-%d-%d@other.Rcpt", i, j); ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod , &status); SM_TEST(ret == RT_IBDB_RCPT); if (sm_is_err(ret)) goto end; SM_TEST(sm_memeq(sm_str_getdata(str), sm_str_getdata(rcpt->ibr_pa), sm_str_getlen(rcpt->ibr_pa))); } ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status); if (sm_is_err(ret) && WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATE) && WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATED)) { SM_TEST(SM_IO_EOF == ret || sm_error_value(ret) == ENOENT || sm_error_perm(SM_EM_IO, EIO) == ret); if (!(SM_IO_EOF == ret || sm_error_value(ret) == ENOENT || sm_error_perm(SM_EM_IO, EIO) == ret)) sm_io_fprintf(smioerr, "sev=ERR, where=2, ibdbr_get%=#x\n" , ret); } else { SM_TEST(ret == RT_IBDB_TA); if (sm_is_err(ret)) break; /* check ta content?? */ } SM_CSTR_FREE(ibdb_ta->ibt_cdb_id); } end: error: if (ibdb_ta != NULL) { SM_STR_FREE(ibdb_ta->ibt_mail_pa); sm_free(ibdb_ta); } if (rcpt != NULL) { SM_STR_FREE(rcpt->ibr_pa); sm_free(rcpt); } SM_STR_FREE(str); if (ibdbr_ctx != NULL) { ret = ibdbr_close(ibdbr_ctx); SM_TEST(ret == SM_SUCCESS); } return ret; } static void usage(const char *prg) { sm_io_fprintf(smioerr, "usage: %s [options]\n" "-1 write one (open) transaction at begin\n" "-a test header append records\n" "-I generate incomplete IBDB file\n" "-i n n iterations\n" "-l n use length n for header modification string\n" "-m n maximum size of IBDB file\n" "-p test header prepend records\n" "-R test header removal records\n" "-r read only\n" "-t n truncate last IBDB file by n bytes before reading\n" "-V increase verbosity\n" "-w write only\n" , prg); exit(EX_USAGE); } int main(int argc, char *argv[]) { int iter, c, maxs; sm_ret_T ret; uint flags; bool readonly; bool writeonly; bool incomplete; char *base_dir; iter = 100; flags = 0; maxs = IBDBSIZE; readonly = false; writeonly = false; incomplete = false; base_dir = NULL; while ((c = getopt(argc, argv, "1ab:HIi:l:m:n:pRrt:Vw")) != -1) { switch (c) { case '1': flags |= WRIBDB_FL_1OPENTA; break; case 'a': flags |= WRIBDB_FL_HDR_APP; break; case 'b': base_dir = strdup(optarg); if (NULL == base_dir) return EX_OSERR; break; #if SM_HEAP_CHECK case 'H': SmHeapCheck = atoi(optarg); break; #endif case 'I': incomplete = true; flags |= WRIBDB_FL_INCOMPL; break; case 'i': iter = strtol(optarg, NULL, 0); if (iter <= 0) return EX_USAGE; break; case 'l': long_str_len = strtol(optarg, NULL, 0); if (long_str_len <= 256) return EX_USAGE; flags |= WRIBDB_FL_LONG; break; case 'm': maxs = strtol(optarg, NULL, 0); if (maxs <= 0) return EX_USAGE; break; case 'n': rcpts_per_ta = strtol(optarg, NULL, 0); if (rcpts_per_ta <= 0) return EX_USAGE; break; case 'p': flags |= WRIBDB_FL_HDR_PRE; break; case 'R': flags |= WRIBDB_FL_HDR_REM; break; case 'r': readonly = true; break; case 't': n_trunc = strtoul(optarg, NULL, 0); if (n_trunc <= 0) return EX_USAGE; flags |= WRIBDB_FL_TRUNCATE; break; case 'V': ++Verbose; break; case 'w': writeonly = true; break; default: usage(argv[0]); /* NOTREACHED */ return EX_USAGE; } } sm_test_begin(argc, argv, "test sm_idb_0"); if (readonly) ret = SM_SUCCESS; else ret = testidbwr(base_dir, iter, maxs, flags, NULL, NULL); if (ret == SM_SUCCESS && !incomplete && !writeonly) ret = testidbr(base_dir, iter, maxs, flags); return sm_test_end(); }