/* * Copyright (c) 2004-2006 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_RCSID("@(#)$Id: t-cdb-0.c,v 1.15 2006/07/18 02:43:18 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/io.h" #include "sm/sysexits.h" #include "sm/cdb.h" #if TEST_CDB_BC #include "cdbbf.h" #endif #include "sm/test.h" #define SM_BUF_SIZE (4 * 1024) #define SM_BF_SIZE (8 * 1024) #if TEST_CDB_BC extern sm_stream_T SmCDBStL; # define CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, mode, instance, cdb_id) cdb_open_wr_vector(cdb_ctx, ta_id, dfp, mode, instance, &SmCDBStL, SM_BF_SIZE, cdb_id) #else # define CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, mode, instance, cdb_id) cdb_open_write(cdb_ctx, ta_id, dfp, mode, instance, cdb_id) #endif /* ** CDB_TEST -- simple CDB test ** ** Parameters: ** base -- base name for CDB ** ** Returns: ** usual sm_error code */ static sm_ret_T cdb_test(const char *base) { size_t i; sm_ret_T ret; cdb_ctx_P cdb_ctx; cdb_id_P cdb_id; sm_file_T *dfp; ssize_t byteswritten, bytesread; #if TEST_CDB_BC sm_file_T *dfpr; int r; struct stat sb; #endif sessta_id_T ta_id; uchar wbuf[SM_BUF_SIZE], wbuf2[SM_BUF_SIZE], rbuf[SM_BUF_SIZE]; dfp = NULL; cdb_id = NULL; SM_ASSERT(sizeof(rbuf) == sizeof(wbuf)); ret = cdb_start(base, &cdb_ctx); SM_TEST_E(SM_SUCCESS == ret); for (i = 0; i < sizeof(wbuf); i++) { wbuf[i] = 'A' + (i % 32); wbuf2[i] = '0' + (i % 32); if (i % 78 == 0) wbuf[i] = wbuf2[i] = '\n'; } sm_snprintf(ta_id, sizeof(ta_id), SMTPS_STID_FORMAT, (ulonglong_T) 1, 2); ret = CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, SM_IO_WREXCL, 0, &cdb_id); SM_TEST_E(SM_SUCCESS == ret); /* write some stuff ... */ ret = cdb_write(cdb_ctx, dfp, (uchar *) wbuf, sizeof(wbuf), &byteswritten); SM_TEST_E(SM_SUCCESS == ret); SM_TEST(byteswritten == sizeof(wbuf)); #if TEST_CDB_BC SM_TEST_E(cdb_id != NULL); r = stat(cdbf_path(dfp), &sb); SM_TEST(r < 0); SM_TEST(ENOENT == errno); #endif ret = cdb_commit(cdb_ctx, dfp); SM_TEST(SM_SUCCESS == ret); #if TEST_CDB_BC SM_TEST_E(cdb_id != NULL); r = stat(cdbf_path(dfp), &sb); SM_TEST(0 == r); #endif ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE); SM_TEST(SM_SUCCESS == ret); #if !TEST_CDB_BC /* fails, file exists */ ret = cdb_open_write(cdb_ctx, ta_id, dfp, SM_IO_WREXCL, 0, NULL); SM_TEST(ret != SM_SUCCESS); if (!sm_is_err(ret)) { cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE); goto end; } #endif /* open another instance */ ret = CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, SM_IO_WREXCL, 1, &cdb_id); SM_TEST_E(SM_SUCCESS == ret); SM_TEST_E(cdb_id != NULL); /* write some stuff ... */ ret = cdb_write(cdb_ctx, dfp, (uchar *) wbuf2, sizeof(wbuf2), &byteswritten); SM_TEST(SM_SUCCESS == ret); SM_TEST(byteswritten == sizeof(wbuf2)); ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE); SM_TEST(SM_SUCCESS == ret); /* try to read */ ret = cdb_open_read(cdb_ctx, ta_id, dfp); SM_TEST_E(SM_SUCCESS == ret); SM_TEST_E(dfp != NULL); ret = sm_io_read(dfp, rbuf, sizeof(rbuf), &bytesread); SM_TEST(SM_SUCCESS == ret); SM_TEST(bytesread == sizeof(rbuf)); for (i = 0; i < sizeof(rbuf); i++) { SM_TEST(wbuf[i] == rbuf[i]); if (wbuf[i] != rbuf[i]) break; } ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE); SM_TEST(SM_SUCCESS == ret); ret = cdb_unlink(cdb_ctx, ta_id); SM_TEST(SM_SUCCESS == ret); /* try to read 2nd instance */ ret = cdb_open_read(cdb_ctx, (char *)sm_cstr_data(cdb_id), dfp); SM_TEST(SM_SUCCESS == ret); SM_TEST_E(dfp != NULL); ret = sm_io_read(dfp, rbuf, sizeof(rbuf), &bytesread); SM_TEST(SM_SUCCESS == ret); SM_TEST(bytesread == sizeof(rbuf)); for (i = 0; i < sizeof(rbuf); i++) { SM_TEST(wbuf2[i] == rbuf[i]); if (wbuf2[i] != rbuf[i]) break; } ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE); SM_TEST(SM_SUCCESS == ret); ret = cdb_unlink(cdb_ctx, (char *)sm_cstr_data(cdb_id)); SM_TEST(SM_SUCCESS == ret); #if TEST_CDB_BC sm_snprintf(ta_id, sizeof(ta_id), SMTPS_STID_FORMAT, (ulonglong_T) 2, 3); ret = CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, SM_IO_RDWRCRX, 0, &cdb_id); SM_TEST_E(SM_SUCCESS == ret); /* write some stuff ... */ ret = cdb_write(cdb_ctx, dfp, (uchar *) wbuf, sizeof(wbuf), &byteswritten); SM_TEST(SM_SUCCESS == ret); SM_TEST(byteswritten == sizeof(wbuf)); SM_TEST_E(cdb_id != NULL); r = stat(cdbf_path(dfp), &sb); SM_TEST(r < 0); SM_TEST(ENOENT == errno); ret = sm_io_dup(dfp); SM_TEST(SM_SUCCESS == ret); dfpr = dfp; ret = sm_io_seek(dfpr, 0, SM_IO_SEEK_SET); SM_TEST(SM_SUCCESS == ret); ret = sm_io_read(dfpr, rbuf, sizeof(rbuf), &bytesread); SM_TEST(SM_SUCCESS == ret); SM_TEST(bytesread == sizeof(rbuf)); for (i = 0; i < sizeof(rbuf); i++) { SM_TEST(wbuf[i] == rbuf[i]); if (wbuf[i] != rbuf[i]) break; } #if 0 ret = cdb_commit(cdb_ctx, dfp); SM_TEST(SM_SUCCESS == ret); SM_TEST_E(cdb_id != NULL); r = stat(cdbf_path(dfp), &sb); SM_TEST(0 == r); #endif /* 0 */ ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE); SM_TEST(SM_SUCCESS == ret); ret = cdb_close(cdb_ctx, dfpr, SM_IO_CF_NONE); SM_TEST(SM_SUCCESS == ret); #endif /* TEST_CDB_BC */ error: #if !TEST_CDB_BC end: #endif ret = cdb_end(cdb_ctx); SM_TEST(SM_SUCCESS == ret); return ret; } /* ** USAGE -- usage message ** ** Parameters: ** prg -- program name ** ** Returns: ** none */ static void usage(char *prg) { sm_io_fprintf(smioerr, "usage: %s [options]\n" "perform CDB checks\n" "-b name set base of CDB directory, default: empty\n" " must be empty [= current directory] or end in '/'\n" , prg ); return; } int main(int argc, char *argv[]) { int c; char *base; base = ""; while ((c = getopt(argc, argv, "b:")) != -1) { switch (c) { case 'b': base = strdup(optarg); SM_TEST(base != NULL); if (NULL == base) return EX_OSERR; break; default: usage(argv[0]); return EX_USAGE; } } sm_test_begin(argc, argv, "test cdb 0"); cdb_test(base); return sm_test_end(); }