/* * 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; }