/*
* Copyright (c) 2000-2002, 2004-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* 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: fclose.c,v 1.15 2006/07/18 02:44:21 ca Exp $")
#include "sm/error.h"
#include "sm/time.h"
#include "sm/io.h"
#include "sm/assert.h"
#include "sm/heap.h"
#include "sm/signal.h"
#include "sm/clock.h"
#include "io-int.h"
/*
** SM_IO_CLOSE -- close a file handle/pointer
**
** Parameters:
** fp -- file pointer to be closed
** flags -- ignored
**
** Returns:
** usual sm_error code
**
** Side Effects:
** file pointer 'fp' will no longer be valid.
*/
sm_ret_T
sm_io_close(sm_file_T *fp, int flags)
{
sm_ret_T r, rc;
if (fp == NULL)
return sm_error_perm(SM_EM_IO, EBADF);
SM_IS_FP(fp);
/* Note: this won't be reached if above macro is active */
if (SM_MAGIC_NULL == fp->sm_magic)
return sm_error_perm(SM_EM_IO, EBADF);
if (f_close(*fp) == NULL)
{
/* no close function! */
return sm_error_perm(SM_EM_IO, ENODEV);
}
if (fp->f_dup_cnt > 0)
{
/* decrement file pointer open count */
fp->f_dup_cnt--;
return SM_SUCCESS;
}
/* No more duplicates of file pointer. Flush buffer and close */
r = SM_SUCCESS;
if ((f_flags(*fp) & SMWR) != 0 && (flags & SM_IO_CF_RM) == 0)
r = sm_flush(fp);
rc = (*f_close(*fp))(fp, flags);
if (sm_is_err(rc))
r = rc;
if (sm_io_double(fp))
{
if (f_rd_flags(*fp) & SMMBF)
{
if (f_bfbase(*fp) == f_rd_bfbase(*fp))
f_bfbase(*fp) = NULL;
SM_FREE(f_rd_bfbase(*fp));
f_rd_flags(*fp) = 0;
f_rd_r(*fp) = 0;
}
if (f_wr_flags(*fp) & SMMBF)
{
if (f_bfbase(*fp) == f_wr_bfbase(*fp))
f_bfbase(*fp) = NULL;
SM_FREE(f_wr_bfbase(*fp));
f_wr_flags(*fp) = 0;
f_wr_w(*fp) = 0;
}
/*
** If the file was only used for either reading or writing
** then f_bf is neither the read nor the write buffer.
** fixme: this is a hack (see checks above), it should probably
** be fixed in some other place, i.e., instead of having
** three buffers (sm_buf_T) have only two in all cases,
** or use two buffers and one pointer to them (which
** requires another indirection).
*/
if (f_flags(*fp) & SMMBF && f_bfbase(*fp) != NULL)
SM_FREE(f_bfbase(*fp));
}
else if (f_flags(*fp) & SMMBF)
SM_FREE(f_bfbase(*fp));
f_flags(*fp) = 0; /* clear flags */
fp->sm_magic = SM_MAGIC_NULL; /* Release this sm_file_T for reuse. */
f_r(*fp) = f_w(*fp) = 0; /* Mess up if reaccessed. */
return r;
}
syntax highlighted by Code2HTML, v. 0.9.1