diff options
Diffstat (limited to 'contrib/sendmail/src/bf.c')
-rw-r--r-- | contrib/sendmail/src/bf.c | 864 |
1 files changed, 0 insertions, 864 deletions
diff --git a/contrib/sendmail/src/bf.c b/contrib/sendmail/src/bf.c deleted file mode 100644 index b31ce7e..0000000 --- a/contrib/sendmail/src/bf.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * Copyright (c) 1999-2002, 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. - * - * Contributed by Exactis.com, Inc. - * - */ - -/* -** This is in transition. Changed from the original bf_torek.c code -** to use sm_io function calls directly rather than through stdio -** translation layer. Will be made a built-in file type of libsm -** next (once safeopen() linkable from libsm). -*/ - -#include <sm/gen.h> -SM_RCSID("@(#)$Id: bf.c,v 8.62 2006/03/31 18:45:56 ca Exp $") - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/uio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include "sendmail.h" -#include "bf.h" - -#include <syslog.h> - -/* bf io functions */ -static ssize_t sm_bfread __P((SM_FILE_T *, char *, size_t)); -static ssize_t sm_bfwrite __P((SM_FILE_T *, const char *, size_t)); -static off_t sm_bfseek __P((SM_FILE_T *, off_t, int)); -static int sm_bfclose __P((SM_FILE_T *)); -static int sm_bfcommit __P((SM_FILE_T *)); -static int sm_bftruncate __P((SM_FILE_T *)); - -static int sm_bfopen __P((SM_FILE_T *, const void *, int, const void *)); -static int sm_bfsetinfo __P((SM_FILE_T *, int , void *)); -static int sm_bfgetinfo __P((SM_FILE_T *, int , void *)); - -/* -** Data structure for storing information about each buffered file -** (Originally in sendmail/bf_torek.h for the curious.) -*/ - -struct bf -{ - bool bf_committed; /* Has this buffered file been committed? */ - bool bf_ondisk; /* On disk: committed or buffer overflow */ - long bf_flags; - int bf_disk_fd; /* If on disk, associated file descriptor */ - char *bf_buf; /* Memory buffer */ - int bf_bufsize; /* Length of above buffer */ - int bf_buffilled; /* Bytes of buffer actually filled */ - char *bf_filename; /* Name of buffered file, if ever committed */ - MODE_T bf_filemode; /* Mode of buffered file, if ever committed */ - off_t bf_offset; /* Currect file offset */ - int bf_size; /* Total current size of file */ -}; - -#ifdef BF_STANDALONE -# define OPEN(fn, omode, cmode, sff) open(fn, omode, cmode) -#else /* BF_STANDALONE */ -# define OPEN(fn, omode, cmode, sff) safeopen(fn, omode, cmode, sff) -#endif /* BF_STANDALONE */ - -struct bf_info -{ - char *bi_filename; - MODE_T bi_fmode; - size_t bi_bsize; - long bi_flags; -}; - -/* -** SM_BFOPEN -- the "base" open function called by sm_io_open() for the -** internal, file-type-specific info setup. -** -** Parameters: -** fp -- file pointer being filled-in for file being open'd -** info -- information about file being opened -** flags -- ignored -** rpool -- ignored (currently) -** -** Returns: -** Failure: -1 and sets errno -** Success: 0 (zero) -*/ - -static int -sm_bfopen(fp, info, flags, rpool) - SM_FILE_T *fp; - const void *info; - int flags; - const void *rpool; -{ - char *filename; - MODE_T fmode; - size_t bsize; - long sflags; - struct bf *bfp; - int l; - struct stat st; - - filename = ((struct bf_info *) info)->bi_filename; - fmode = ((struct bf_info *) info)->bi_fmode; - bsize = ((struct bf_info *) info)->bi_bsize; - sflags = ((struct bf_info *) info)->bi_flags; - - /* Sanity checks */ - if (*filename == '\0') - { - /* Empty filename string */ - errno = ENOENT; - return -1; - } - if (stat(filename, &st) == 0) - { - /* File already exists on disk */ - errno = EEXIST; - return -1; - } - - /* Allocate memory */ - bfp = (struct bf *) sm_malloc(sizeof(struct bf)); - if (bfp == NULL) - { - errno = ENOMEM; - return -1; - } - - /* Assign data buffer */ - /* A zero bsize is valid, just don't allocate memory */ - if (bsize > 0) - { - bfp->bf_buf = (char *) sm_malloc(bsize); - if (bfp->bf_buf == NULL) - { - bfp->bf_bufsize = 0; - sm_free(bfp); - errno = ENOMEM; - return -1; - } - } - else - bfp->bf_buf = NULL; - - /* Nearly home free, just set all the parameters now */ - bfp->bf_committed = false; - bfp->bf_ondisk = false; - bfp->bf_flags = sflags; - bfp->bf_bufsize = bsize; - bfp->bf_buffilled = 0; - l = strlen(filename) + 1; - bfp->bf_filename = (char *) sm_malloc(l); - if (bfp->bf_filename == NULL) - { - if (bfp->bf_buf != NULL) - sm_free(bfp->bf_buf); - sm_free(bfp); - errno = ENOMEM; - return -1; - } - (void) sm_strlcpy(bfp->bf_filename, filename, l); - bfp->bf_filemode = fmode; - bfp->bf_offset = 0; - bfp->bf_size = 0; - bfp->bf_disk_fd = -1; - fp->f_cookie = bfp; - - if (tTd(58, 8)) - sm_dprintf("sm_bfopen(%s)\n", filename); - - return 0; -} - -/* -** BFOPEN -- create a new buffered file -** -** Parameters: -** filename -- the file's name -** fmode -- what mode the file should be created as -** bsize -- amount of buffer space to allocate (may be 0) -** flags -- if running under sendmail, passed directly to safeopen -** -** Returns: -** a SM_FILE_T * which may then be used with stdio functions, -** or NULL on failure. SM_FILE_T * is opened for writing -** "SM_IO_WHAT_VECTORS"). -** -** Side Effects: -** none. -** -** Sets errno: -** any value of errno specified by sm_io_setinfo_type() -** any value of errno specified by sm_io_open() -** any value of errno specified by sm_io_setinfo() -*/ - -#ifdef __STDC__ -/* -** XXX This is a temporary hack since MODE_T on HP-UX 10.x is short. -** If we use K&R here, the compiler will complain about -** Inconsistent parameter list declaration -** due to the change from short to int. -*/ - -SM_FILE_T * -bfopen(char *filename, MODE_T fmode, size_t bsize, long flags) -#else /* __STDC__ */ -SM_FILE_T * -bfopen(filename, fmode, bsize, flags) - char *filename; - MODE_T fmode; - size_t bsize; - long flags; -#endif /* __STDC__ */ -{ - MODE_T omask; - SM_FILE_T SM_IO_SET_TYPE(vector, BF_FILE_TYPE, sm_bfopen, sm_bfclose, - sm_bfread, sm_bfwrite, sm_bfseek, sm_bfgetinfo, sm_bfsetinfo, - SM_TIME_FOREVER); - struct bf_info info; - - /* - ** Apply current umask to fmode as it may change by the time - ** the file is actually created. fmode becomes the true - ** permissions of the file, which OPEN() must obey. - */ - - omask = umask(0); - fmode &= ~omask; - (void) umask(omask); - - SM_IO_INIT_TYPE(vector, BF_FILE_TYPE, sm_bfopen, sm_bfclose, - sm_bfread, sm_bfwrite, sm_bfseek, sm_bfgetinfo, sm_bfsetinfo, - SM_TIME_FOREVER); - info.bi_filename = filename; - info.bi_fmode = fmode; - info.bi_bsize = bsize; - info.bi_flags = flags; - - return sm_io_open(&vector, SM_TIME_DEFAULT, &info, SM_IO_RDWR, NULL); -} - -/* -** SM_BFGETINFO -- returns info about an open file pointer -** -** Parameters: -** fp -- file pointer to get info about -** what -- type of info to obtain -** valp -- thing to return the info in -*/ - -static int -sm_bfgetinfo(fp, what, valp) - SM_FILE_T *fp; - int what; - void *valp; -{ - struct bf *bfp; - - bfp = (struct bf *) fp->f_cookie; - switch (what) - { - case SM_IO_WHAT_FD: - return bfp->bf_disk_fd; - case SM_IO_WHAT_SIZE: - return bfp->bf_size; - default: - return -1; - } -} - -/* -** SM_BFCLOSE -- close a buffered file -** -** Parameters: -** fp -- cookie of file to close -** -** Returns: -** 0 to indicate success -** -** Side Effects: -** deletes backing file, sm_frees memory. -** -** Sets errno: -** never. -*/ - -static int -sm_bfclose(fp) - SM_FILE_T *fp; -{ - struct bf *bfp; - - /* Cast cookie back to correct type */ - bfp = (struct bf *) fp->f_cookie; - - /* Need to clean up the file */ - if (bfp->bf_ondisk && !bfp->bf_committed) - unlink(bfp->bf_filename); - sm_free(bfp->bf_filename); - - if (bfp->bf_disk_fd != -1) - close(bfp->bf_disk_fd); - - /* Need to sm_free the buffer */ - if (bfp->bf_bufsize > 0) - sm_free(bfp->bf_buf); - - /* Finally, sm_free the structure */ - sm_free(bfp); - return 0; -} - -/* -** SM_BFREAD -- read a buffered file -** -** Parameters: -** cookie -- cookie of file to read -** buf -- buffer to fill -** nbytes -- how many bytes to read -** -** Returns: -** number of bytes read or -1 indicate failure -** -** Side Effects: -** none. -** -*/ - -static ssize_t -sm_bfread(fp, buf, nbytes) - SM_FILE_T *fp; - char *buf; - size_t nbytes; -{ - struct bf *bfp; - ssize_t count = 0; /* Number of bytes put in buf so far */ - int retval; - - /* Cast cookie back to correct type */ - bfp = (struct bf *) fp->f_cookie; - - if (bfp->bf_offset < bfp->bf_buffilled) - { - /* Need to grab some from buffer */ - count = nbytes; - if ((bfp->bf_offset + count) > bfp->bf_buffilled) - count = bfp->bf_buffilled - bfp->bf_offset; - - memcpy(buf, bfp->bf_buf + bfp->bf_offset, count); - } - - if ((bfp->bf_offset + nbytes) > bfp->bf_buffilled) - { - /* Need to grab some from file */ - if (!bfp->bf_ondisk) - { - /* Oops, the file doesn't exist. EOF. */ - if (tTd(58, 8)) - sm_dprintf("sm_bfread(%s): to disk\n", - bfp->bf_filename); - goto finished; - } - - /* Catch a read() on an earlier failed write to disk */ - if (bfp->bf_disk_fd < 0) - { - errno = EIO; - return -1; - } - - if (lseek(bfp->bf_disk_fd, - bfp->bf_offset + count, SEEK_SET) < 0) - { - if ((errno == EINVAL) || (errno == ESPIPE)) - { - /* - ** stdio won't be expecting these - ** errnos from read()! Change them - ** into something it can understand. - */ - - errno = EIO; - } - return -1; - } - - while (count < nbytes) - { - retval = read(bfp->bf_disk_fd, - buf + count, - nbytes - count); - if (retval < 0) - { - /* errno is set implicitly by read() */ - return -1; - } - else if (retval == 0) - goto finished; - else - count += retval; - } - } - -finished: - bfp->bf_offset += count; - return count; -} - -/* -** SM_BFSEEK -- seek to a position in a buffered file -** -** Parameters: -** fp -- fp of file to seek -** offset -- position to seek to -** whence -- how to seek -** -** Returns: -** new file offset or -1 indicate failure -** -** Side Effects: -** none. -** -*/ - -static off_t -sm_bfseek(fp, offset, whence) - SM_FILE_T *fp; - off_t offset; - int whence; - -{ - struct bf *bfp; - - /* Cast cookie back to correct type */ - bfp = (struct bf *) fp->f_cookie; - - switch (whence) - { - case SEEK_SET: - bfp->bf_offset = offset; - break; - - case SEEK_CUR: - bfp->bf_offset += offset; - break; - - case SEEK_END: - bfp->bf_offset = bfp->bf_size + offset; - break; - - default: - errno = EINVAL; - return -1; - } - return bfp->bf_offset; -} - -/* -** SM_BFWRITE -- write to a buffered file -** -** Parameters: -** fp -- fp of file to write -** buf -- data buffer -** nbytes -- how many bytes to write -** -** Returns: -** number of bytes written or -1 indicate failure -** -** Side Effects: -** may create backing file if over memory limit for file. -** -*/ - -static ssize_t -sm_bfwrite(fp, buf, nbytes) - SM_FILE_T *fp; - const char *buf; - size_t nbytes; -{ - struct bf *bfp; - ssize_t count = 0; /* Number of bytes written so far */ - int retval; - - /* Cast cookie back to correct type */ - bfp = (struct bf *) fp->f_cookie; - - /* If committed, go straight to disk */ - if (bfp->bf_committed) - { - if (lseek(bfp->bf_disk_fd, bfp->bf_offset, SEEK_SET) < 0) - { - if ((errno == EINVAL) || (errno == ESPIPE)) - { - /* - ** stdio won't be expecting these - ** errnos from write()! Change them - ** into something it can understand. - */ - - errno = EIO; - } - return -1; - } - - count = write(bfp->bf_disk_fd, buf, nbytes); - if (count < 0) - { - /* errno is set implicitly by write() */ - return -1; - } - goto finished; - } - - if (bfp->bf_offset < bfp->bf_bufsize) - { - /* Need to put some in buffer */ - count = nbytes; - if ((bfp->bf_offset + count) > bfp->bf_bufsize) - count = bfp->bf_bufsize - bfp->bf_offset; - - memcpy(bfp->bf_buf + bfp->bf_offset, buf, count); - if ((bfp->bf_offset + count) > bfp->bf_buffilled) - bfp->bf_buffilled = bfp->bf_offset + count; - } - - if ((bfp->bf_offset + nbytes) > bfp->bf_bufsize) - { - /* Need to put some in file */ - if (!bfp->bf_ondisk) - { - MODE_T omask; - int save_errno; - - /* Clear umask as bf_filemode are the true perms */ - omask = umask(0); - retval = OPEN(bfp->bf_filename, - O_RDWR | O_CREAT | O_TRUNC | QF_O_EXTRA, - bfp->bf_filemode, bfp->bf_flags); - save_errno = errno; - (void) umask(omask); - errno = save_errno; - - /* Couldn't create file: failure */ - if (retval < 0) - { - /* - ** stdio may not be expecting these - ** errnos from write()! Change to - ** something which it can understand. - ** Note that ENOSPC and EDQUOT are saved - ** because they are actually valid for - ** write(). - */ - - if (!(errno == ENOSPC -#ifdef EDQUOT - || errno == EDQUOT -#endif /* EDQUOT */ - )) - errno = EIO; - - return -1; - } - bfp->bf_disk_fd = retval; - bfp->bf_ondisk = true; - } - - /* Catch a write() on an earlier failed write to disk */ - if (bfp->bf_ondisk && bfp->bf_disk_fd < 0) - { - errno = EIO; - return -1; - } - - if (lseek(bfp->bf_disk_fd, - bfp->bf_offset + count, SEEK_SET) < 0) - { - if ((errno == EINVAL) || (errno == ESPIPE)) - { - /* - ** stdio won't be expecting these - ** errnos from write()! Change them into - ** something which it can understand. - */ - - errno = EIO; - } - return -1; - } - - while (count < nbytes) - { - retval = write(bfp->bf_disk_fd, buf + count, - nbytes - count); - if (retval < 0) - { - /* errno is set implicitly by write() */ - return -1; - } - else - count += retval; - } - } - -finished: - bfp->bf_offset += count; - if (bfp->bf_offset > bfp->bf_size) - bfp->bf_size = bfp->bf_offset; - return count; -} - -/* -** BFREWIND -- rewinds the SM_FILE_T * -** -** Parameters: -** fp -- SM_FILE_T * to rewind -** -** Returns: -** 0 on success, -1 on error -** -** Side Effects: -** rewinds the SM_FILE_T * and puts it into read mode. Normally -** one would bfopen() a file, write to it, then bfrewind() and -** fread(). If fp is not a buffered file, this is equivalent to -** rewind(). -** -** Sets errno: -** any value of errno specified by sm_io_rewind() -*/ - -int -bfrewind(fp) - SM_FILE_T *fp; -{ - (void) sm_io_flush(fp, SM_TIME_DEFAULT); - sm_io_clearerr(fp); /* quicker just to do it */ - return sm_io_seek(fp, SM_TIME_DEFAULT, 0, SM_IO_SEEK_SET); -} - -/* -** SM_BFCOMMIT -- "commits" the buffered file -** -** Parameters: -** fp -- SM_FILE_T * to commit to disk -** -** Returns: -** 0 on success, -1 on error -** -** Side Effects: -** Forces the given SM_FILE_T * to be written to disk if it is not -** already, and ensures that it will be kept after closing. If -** fp is not a buffered file, this is a no-op. -** -** Sets errno: -** any value of errno specified by open() -** any value of errno specified by write() -** any value of errno specified by lseek() -*/ - -static int -sm_bfcommit(fp) - SM_FILE_T *fp; -{ - struct bf *bfp; - int retval; - int byteswritten; - - /* Get associated bf structure */ - bfp = (struct bf *) fp->f_cookie; - - /* If already committed, noop */ - if (bfp->bf_committed) - return 0; - - /* Do we need to open a file? */ - if (!bfp->bf_ondisk) - { - int save_errno; - MODE_T omask; - struct stat st; - - if (tTd(58, 8)) - { - sm_dprintf("bfcommit(%s): to disk\n", bfp->bf_filename); - if (tTd(58, 32)) - sm_dprintf("bfcommit(): filemode %o flags %ld\n", - bfp->bf_filemode, bfp->bf_flags); - } - - if (stat(bfp->bf_filename, &st) == 0) - { - errno = EEXIST; - return -1; - } - - /* Clear umask as bf_filemode are the true perms */ - omask = umask(0); - retval = OPEN(bfp->bf_filename, - O_RDWR | O_CREAT | O_EXCL | QF_O_EXTRA, - bfp->bf_filemode, bfp->bf_flags); - save_errno = errno; - (void) umask(omask); - - /* Couldn't create file: failure */ - if (retval < 0) - { - /* errno is set implicitly by open() */ - errno = save_errno; - return -1; - } - - bfp->bf_disk_fd = retval; - bfp->bf_ondisk = true; - } - - /* Write out the contents of our buffer, if we have any */ - if (bfp->bf_buffilled > 0) - { - byteswritten = 0; - - if (lseek(bfp->bf_disk_fd, 0, SEEK_SET) < 0) - { - /* errno is set implicitly by lseek() */ - return -1; - } - - while (byteswritten < bfp->bf_buffilled) - { - retval = write(bfp->bf_disk_fd, - bfp->bf_buf + byteswritten, - bfp->bf_buffilled - byteswritten); - if (retval < 0) - { - /* errno is set implicitly by write() */ - return -1; - } - else - byteswritten += retval; - } - } - bfp->bf_committed = true; - - /* Invalidate buf; all goes to file now */ - bfp->bf_buffilled = 0; - if (bfp->bf_bufsize > 0) - { - /* Don't need buffer anymore; free it */ - bfp->bf_bufsize = 0; - sm_free(bfp->bf_buf); - } - return 0; -} - -/* -** SM_BFTRUNCATE -- rewinds and truncates the SM_FILE_T * -** -** Parameters: -** fp -- SM_FILE_T * to truncate -** -** Returns: -** 0 on success, -1 on error -** -** Side Effects: -** rewinds the SM_FILE_T *, truncates it to zero length, and puts -** it into write mode. -** -** Sets errno: -** any value of errno specified by fseek() -** any value of errno specified by ftruncate() -*/ - -static int -sm_bftruncate(fp) - SM_FILE_T *fp; -{ - struct bf *bfp; - - if (bfrewind(fp) < 0) - return -1; - - /* Get bf structure */ - bfp = (struct bf *) fp->f_cookie; - bfp->bf_buffilled = 0; - bfp->bf_size = 0; - - /* Need to zero the buffer */ - if (bfp->bf_bufsize > 0) - memset(bfp->bf_buf, '\0', bfp->bf_bufsize); - if (bfp->bf_ondisk) - { -#if NOFTRUNCATE - /* XXX: Not much we can do except rewind it */ - errno = EINVAL; - return -1; -#else /* NOFTRUNCATE */ - return ftruncate(bfp->bf_disk_fd, 0); -#endif /* NOFTRUNCATE */ - } - return 0; -} - -/* -** SM_BFSETINFO -- set/change info for an open file pointer -** -** Parameters: -** fp -- file pointer to get info about -** what -- type of info to set/change -** valp -- thing to set/change the info to -** -*/ - -static int -sm_bfsetinfo(fp, what, valp) - SM_FILE_T *fp; - int what; - void *valp; -{ - struct bf *bfp; - int bsize; - - /* Get bf structure */ - bfp = (struct bf *) fp->f_cookie; - switch (what) - { - case SM_BF_SETBUFSIZE: - bsize = *((int *) valp); - bfp->bf_bufsize = bsize; - - /* A zero bsize is valid, just don't allocate memory */ - if (bsize > 0) - { - bfp->bf_buf = (char *) sm_malloc(bsize); - if (bfp->bf_buf == NULL) - { - bfp->bf_bufsize = 0; - errno = ENOMEM; - return -1; - } - } - else - bfp->bf_buf = NULL; - return 0; - case SM_BF_COMMIT: - return sm_bfcommit(fp); - case SM_BF_TRUNCATE: - return sm_bftruncate(fp); - case SM_BF_TEST: - return 1; /* always */ - default: - errno = EINVAL; - return -1; - } -} |