/*
 * Copyright (c) 2003-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_RCSID("@(#)$Id: edbfs.c,v 1.11 2007/06/15 02:53:00 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/string.h"
#include "edb-int.h"
#include "sm/fs.h"
#include "sm/edbfs.h"

/*
**  HACK
**  How to determine which DEFEDB directories are actually in use?
**  todo: refer to configuration data?
*/

#define EDB_DIRS	1	/* currently only one directory */
#define EDB_MAX_DIRNAME	PATH_MAX

/* EDB FileSystem ConTeXt */
struct edb_fsctx_S
{
	fs_ctx_P	efx_fs_ctx;
	char		efx_dirs[EDB_DIRS][EDB_MAX_DIRNAME];
	int		efx_fs_idx[EDB_DIRS];
};

/*
**  EDB_CTX_CLOSE -- close a EDB context
**
**	Parameters:
**		edb_fsctx -- EDB context
**
**	Returns:
**		SM_SUCCESS
**
**	Last code review: 2005-04-23 21:16:52
**	Last code change:
*/

sm_ret_T
edb_fsctx_close(edb_fsctx_P edb_fsctx)
{
	if (edb_fsctx == NULL)
		return SM_SUCCESS;
	sm_free_size(edb_fsctx, sizeof(*edb_fsctx));
	return SM_SUCCESS;
}

/*
**  EDB_CTX_OPEN -- open a EDB FS context
**
**	Parameters:
**		fs_ctx -- FS context
**		base_path -- path to base directory
**		pedb_fsctx -- (pointer to) EDB context (output)
**		pkbfree -- (pointer to) free space (KB) (output)
**
**	Returns:
**		usual sm_error code; ENOMEM, etc
**
**	Side Effects: may fill efx_fs_ctx partially
**
**	Last code review: 2005-04-23 21:19:39
**	Last code change: 2005-04-23 21:19:23
*/

sm_ret_T
edb_fsctx_open(fs_ctx_P fs_ctx, const char *base_path, edb_fsctx_P *pedb_fsctx, ulong *pkbfree)
{
	sm_ret_T ret;
	int j;
	uint u;
	size_t l;
	ulong kbfree, freemin;
	edb_fsctx_P edb_fsctx;

	SM_REQUIRE(pedb_fsctx != NULL);
	edb_fsctx = (edb_fsctx_P) sm_zalloc(sizeof(*edb_fsctx));
	if (edb_fsctx == NULL)
		return sm_error_temp(SM_EM_EDB, ENOMEM);

	SM_IS_FS_CTX(fs_ctx);
	edb_fsctx->efx_fs_ctx = fs_ctx;

	if (base_path != NULL) {
		l = strlcpy(edb_fsctx->efx_dirs[0], base_path,
			sizeof(edb_fsctx->efx_dirs[0]));
		if (l >= sizeof(edb_fsctx->efx_dirs[0])) {
			ret = sm_error_perm(SM_EM_EDB, SM_E_2BIG);
			goto error;
		}
	}
	l = strlcat(edb_fsctx->efx_dirs[0], EDB_HOME,
			sizeof(edb_fsctx->efx_dirs[0]));
	if (l >= sizeof(edb_fsctx->efx_dirs[0])) {
		ret = sm_error_perm(SM_EM_EDB, SM_E_2BIG);
		goto error;
	}

	freemin = LONG_MAX;
	for (u = 0; u < EDB_DIRS; u++)
	{
		ret = fs_new(edb_fsctx->efx_fs_ctx, edb_fsctx->efx_dirs[u], &j);
		if (sm_is_err(ret))
			goto error;
		edb_fsctx->efx_fs_idx[u] = j;
		ret = fs_getfree(edb_fsctx->efx_fs_ctx, j, &kbfree);
		if (sm_is_err(ret))
			goto error;
		if (kbfree < freemin)
			freemin = kbfree;
	}
	*pkbfree = freemin;
	*pedb_fsctx = edb_fsctx;
	return SM_SUCCESS;

  error:
	if (edb_fsctx != NULL)
		sm_free_size(edb_fsctx, sizeof(*edb_fsctx));
	return ret;
}

/*
**  EDB_FS_GETFREE -- get free space in EDB FS
**
**	Parameters:
**		edb_fs_ctx -- EDB FS context
**		pkbfree -- (pointer to) free space (KB) (output)
**
**	Returns:
**		usual sm_error code; fs_getfree()
**
**	Last code review: 2005-04-21 23:48:48
**	Last code change:
*/

sm_ret_T
edb_fs_getfree(edb_fsctx_P edb_fsctx, ulong *pkbfree)
{
	sm_ret_T ret;
	int i;
	ulong kbfree, freemin;

	SM_REQUIRE(edb_fsctx != NULLPTR);
	SM_REQUIRE(pkbfree != NULLPTR);

	ret = SM_SUCCESS;
	freemin = LONG_MAX;
	for (i = 0; i < EDB_DIRS; i++)
	{
		ret = fs_getfree(edb_fsctx->efx_fs_ctx,
				edb_fsctx->efx_fs_idx[i], &kbfree);
		if (!sm_is_err(ret) && kbfree < freemin)
			freemin = kbfree;
	}
	*pkbfree = freemin;
	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1