140266059SGregory Neil Shapiro /* 25dd76dd0SGregory Neil Shapiro * Copyright (c) 1999-2002, 2004, 2006 Proofpoint, Inc. and its suppliers. 340266059SGregory Neil Shapiro * All rights reserved. 440266059SGregory Neil Shapiro * 540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 740266059SGregory Neil Shapiro * the sendmail distribution. 840266059SGregory Neil Shapiro * 940266059SGregory Neil Shapiro * Contributed by Exactis.com, Inc. 1040266059SGregory Neil Shapiro * 1140266059SGregory Neil Shapiro */ 1240266059SGregory Neil Shapiro 1340266059SGregory Neil Shapiro /* 1440266059SGregory Neil Shapiro ** This is in transition. Changed from the original bf_torek.c code 1540266059SGregory Neil Shapiro ** to use sm_io function calls directly rather than through stdio 1640266059SGregory Neil Shapiro ** translation layer. Will be made a built-in file type of libsm 1740266059SGregory Neil Shapiro ** next (once safeopen() linkable from libsm). 1840266059SGregory Neil Shapiro */ 1940266059SGregory Neil Shapiro 2040266059SGregory Neil Shapiro #include <sm/gen.h> 21*4313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: bf.c,v 8.63 2013-11-22 20:51:55 ca Exp $") 2240266059SGregory Neil Shapiro 2340266059SGregory Neil Shapiro #include <sys/types.h> 2440266059SGregory Neil Shapiro #include <sys/stat.h> 2540266059SGregory Neil Shapiro #include <sys/uio.h> 2640266059SGregory Neil Shapiro #include <fcntl.h> 2740266059SGregory Neil Shapiro #include <unistd.h> 2840266059SGregory Neil Shapiro #include <stdlib.h> 2940266059SGregory Neil Shapiro #include <string.h> 3040266059SGregory Neil Shapiro #include <errno.h> 3140266059SGregory Neil Shapiro #include "sendmail.h" 3240266059SGregory Neil Shapiro #include "bf.h" 3340266059SGregory Neil Shapiro 3440266059SGregory Neil Shapiro #include <syslog.h> 3540266059SGregory Neil Shapiro 3640266059SGregory Neil Shapiro /* bf io functions */ 3740266059SGregory Neil Shapiro static ssize_t sm_bfread __P((SM_FILE_T *, char *, size_t)); 3840266059SGregory Neil Shapiro static ssize_t sm_bfwrite __P((SM_FILE_T *, const char *, size_t)); 3940266059SGregory Neil Shapiro static off_t sm_bfseek __P((SM_FILE_T *, off_t, int)); 4040266059SGregory Neil Shapiro static int sm_bfclose __P((SM_FILE_T *)); 41b6bacd31SGregory Neil Shapiro static int sm_bfcommit __P((SM_FILE_T *)); 42b6bacd31SGregory Neil Shapiro static int sm_bftruncate __P((SM_FILE_T *)); 4340266059SGregory Neil Shapiro 4440266059SGregory Neil Shapiro static int sm_bfopen __P((SM_FILE_T *, const void *, int, const void *)); 4540266059SGregory Neil Shapiro static int sm_bfsetinfo __P((SM_FILE_T *, int , void *)); 4640266059SGregory Neil Shapiro static int sm_bfgetinfo __P((SM_FILE_T *, int , void *)); 4740266059SGregory Neil Shapiro 4840266059SGregory Neil Shapiro /* 4940266059SGregory Neil Shapiro ** Data structure for storing information about each buffered file 5040266059SGregory Neil Shapiro ** (Originally in sendmail/bf_torek.h for the curious.) 5140266059SGregory Neil Shapiro */ 5240266059SGregory Neil Shapiro 5340266059SGregory Neil Shapiro struct bf 5440266059SGregory Neil Shapiro { 5540266059SGregory Neil Shapiro bool bf_committed; /* Has this buffered file been committed? */ 5640266059SGregory Neil Shapiro bool bf_ondisk; /* On disk: committed or buffer overflow */ 5740266059SGregory Neil Shapiro long bf_flags; 5840266059SGregory Neil Shapiro int bf_disk_fd; /* If on disk, associated file descriptor */ 5940266059SGregory Neil Shapiro char *bf_buf; /* Memory buffer */ 6040266059SGregory Neil Shapiro int bf_bufsize; /* Length of above buffer */ 6140266059SGregory Neil Shapiro int bf_buffilled; /* Bytes of buffer actually filled */ 6240266059SGregory Neil Shapiro char *bf_filename; /* Name of buffered file, if ever committed */ 6340266059SGregory Neil Shapiro MODE_T bf_filemode; /* Mode of buffered file, if ever committed */ 6440266059SGregory Neil Shapiro off_t bf_offset; /* Currect file offset */ 6540266059SGregory Neil Shapiro int bf_size; /* Total current size of file */ 6640266059SGregory Neil Shapiro }; 6740266059SGregory Neil Shapiro 6840266059SGregory Neil Shapiro #ifdef BF_STANDALONE 6940266059SGregory Neil Shapiro # define OPEN(fn, omode, cmode, sff) open(fn, omode, cmode) 7040266059SGregory Neil Shapiro #else /* BF_STANDALONE */ 7140266059SGregory Neil Shapiro # define OPEN(fn, omode, cmode, sff) safeopen(fn, omode, cmode, sff) 7240266059SGregory Neil Shapiro #endif /* BF_STANDALONE */ 7340266059SGregory Neil Shapiro 7440266059SGregory Neil Shapiro struct bf_info 7540266059SGregory Neil Shapiro { 7640266059SGregory Neil Shapiro char *bi_filename; 7740266059SGregory Neil Shapiro MODE_T bi_fmode; 7840266059SGregory Neil Shapiro size_t bi_bsize; 7940266059SGregory Neil Shapiro long bi_flags; 8040266059SGregory Neil Shapiro }; 8140266059SGregory Neil Shapiro 8240266059SGregory Neil Shapiro /* 8340266059SGregory Neil Shapiro ** SM_BFOPEN -- the "base" open function called by sm_io_open() for the 8440266059SGregory Neil Shapiro ** internal, file-type-specific info setup. 8540266059SGregory Neil Shapiro ** 8640266059SGregory Neil Shapiro ** Parameters: 8740266059SGregory Neil Shapiro ** fp -- file pointer being filled-in for file being open'd 88605302a5SGregory Neil Shapiro ** info -- information about file being opened 8940266059SGregory Neil Shapiro ** flags -- ignored 9040266059SGregory Neil Shapiro ** rpool -- ignored (currently) 9140266059SGregory Neil Shapiro ** 9240266059SGregory Neil Shapiro ** Returns: 9340266059SGregory Neil Shapiro ** Failure: -1 and sets errno 9440266059SGregory Neil Shapiro ** Success: 0 (zero) 9540266059SGregory Neil Shapiro */ 9640266059SGregory Neil Shapiro 9740266059SGregory Neil Shapiro static int 9840266059SGregory Neil Shapiro sm_bfopen(fp, info, flags, rpool) 9940266059SGregory Neil Shapiro SM_FILE_T *fp; 10040266059SGregory Neil Shapiro const void *info; 10140266059SGregory Neil Shapiro int flags; 10240266059SGregory Neil Shapiro const void *rpool; 10340266059SGregory Neil Shapiro { 10440266059SGregory Neil Shapiro char *filename; 10540266059SGregory Neil Shapiro MODE_T fmode; 10640266059SGregory Neil Shapiro size_t bsize; 10740266059SGregory Neil Shapiro long sflags; 10840266059SGregory Neil Shapiro struct bf *bfp; 10940266059SGregory Neil Shapiro int l; 11040266059SGregory Neil Shapiro struct stat st; 11140266059SGregory Neil Shapiro 11240266059SGregory Neil Shapiro filename = ((struct bf_info *) info)->bi_filename; 11340266059SGregory Neil Shapiro fmode = ((struct bf_info *) info)->bi_fmode; 11440266059SGregory Neil Shapiro bsize = ((struct bf_info *) info)->bi_bsize; 11540266059SGregory Neil Shapiro sflags = ((struct bf_info *) info)->bi_flags; 11640266059SGregory Neil Shapiro 11740266059SGregory Neil Shapiro /* Sanity checks */ 11840266059SGregory Neil Shapiro if (*filename == '\0') 11940266059SGregory Neil Shapiro { 12040266059SGregory Neil Shapiro /* Empty filename string */ 12140266059SGregory Neil Shapiro errno = ENOENT; 12240266059SGregory Neil Shapiro return -1; 12340266059SGregory Neil Shapiro } 12440266059SGregory Neil Shapiro if (stat(filename, &st) == 0) 12540266059SGregory Neil Shapiro { 12640266059SGregory Neil Shapiro /* File already exists on disk */ 12740266059SGregory Neil Shapiro errno = EEXIST; 12840266059SGregory Neil Shapiro return -1; 12940266059SGregory Neil Shapiro } 13040266059SGregory Neil Shapiro 13140266059SGregory Neil Shapiro /* Allocate memory */ 13240266059SGregory Neil Shapiro bfp = (struct bf *) sm_malloc(sizeof(struct bf)); 13340266059SGregory Neil Shapiro if (bfp == NULL) 13440266059SGregory Neil Shapiro { 13540266059SGregory Neil Shapiro errno = ENOMEM; 13640266059SGregory Neil Shapiro return -1; 13740266059SGregory Neil Shapiro } 13840266059SGregory Neil Shapiro 13940266059SGregory Neil Shapiro /* Assign data buffer */ 14040266059SGregory Neil Shapiro /* A zero bsize is valid, just don't allocate memory */ 14140266059SGregory Neil Shapiro if (bsize > 0) 14240266059SGregory Neil Shapiro { 14340266059SGregory Neil Shapiro bfp->bf_buf = (char *) sm_malloc(bsize); 14440266059SGregory Neil Shapiro if (bfp->bf_buf == NULL) 14540266059SGregory Neil Shapiro { 14640266059SGregory Neil Shapiro bfp->bf_bufsize = 0; 14740266059SGregory Neil Shapiro sm_free(bfp); 14840266059SGregory Neil Shapiro errno = ENOMEM; 14940266059SGregory Neil Shapiro return -1; 15040266059SGregory Neil Shapiro } 15140266059SGregory Neil Shapiro } 15240266059SGregory Neil Shapiro else 15340266059SGregory Neil Shapiro bfp->bf_buf = NULL; 15440266059SGregory Neil Shapiro 15540266059SGregory Neil Shapiro /* Nearly home free, just set all the parameters now */ 15640266059SGregory Neil Shapiro bfp->bf_committed = false; 15740266059SGregory Neil Shapiro bfp->bf_ondisk = false; 15840266059SGregory Neil Shapiro bfp->bf_flags = sflags; 15940266059SGregory Neil Shapiro bfp->bf_bufsize = bsize; 16040266059SGregory Neil Shapiro bfp->bf_buffilled = 0; 16140266059SGregory Neil Shapiro l = strlen(filename) + 1; 16240266059SGregory Neil Shapiro bfp->bf_filename = (char *) sm_malloc(l); 16340266059SGregory Neil Shapiro if (bfp->bf_filename == NULL) 16440266059SGregory Neil Shapiro { 16540266059SGregory Neil Shapiro if (bfp->bf_buf != NULL) 16640266059SGregory Neil Shapiro sm_free(bfp->bf_buf); 16740266059SGregory Neil Shapiro sm_free(bfp); 16840266059SGregory Neil Shapiro errno = ENOMEM; 16940266059SGregory Neil Shapiro return -1; 17040266059SGregory Neil Shapiro } 17140266059SGregory Neil Shapiro (void) sm_strlcpy(bfp->bf_filename, filename, l); 17240266059SGregory Neil Shapiro bfp->bf_filemode = fmode; 17340266059SGregory Neil Shapiro bfp->bf_offset = 0; 174605302a5SGregory Neil Shapiro bfp->bf_size = 0; 17540266059SGregory Neil Shapiro bfp->bf_disk_fd = -1; 17640266059SGregory Neil Shapiro fp->f_cookie = bfp; 17740266059SGregory Neil Shapiro 17840266059SGregory Neil Shapiro if (tTd(58, 8)) 17940266059SGregory Neil Shapiro sm_dprintf("sm_bfopen(%s)\n", filename); 18040266059SGregory Neil Shapiro 18140266059SGregory Neil Shapiro return 0; 18240266059SGregory Neil Shapiro } 18340266059SGregory Neil Shapiro 18440266059SGregory Neil Shapiro /* 18540266059SGregory Neil Shapiro ** BFOPEN -- create a new buffered file 18640266059SGregory Neil Shapiro ** 18740266059SGregory Neil Shapiro ** Parameters: 18840266059SGregory Neil Shapiro ** filename -- the file's name 18940266059SGregory Neil Shapiro ** fmode -- what mode the file should be created as 19040266059SGregory Neil Shapiro ** bsize -- amount of buffer space to allocate (may be 0) 19140266059SGregory Neil Shapiro ** flags -- if running under sendmail, passed directly to safeopen 19240266059SGregory Neil Shapiro ** 19340266059SGregory Neil Shapiro ** Returns: 19440266059SGregory Neil Shapiro ** a SM_FILE_T * which may then be used with stdio functions, 19540266059SGregory Neil Shapiro ** or NULL on failure. SM_FILE_T * is opened for writing 19640266059SGregory Neil Shapiro ** "SM_IO_WHAT_VECTORS"). 19740266059SGregory Neil Shapiro ** 19840266059SGregory Neil Shapiro ** Side Effects: 19940266059SGregory Neil Shapiro ** none. 20040266059SGregory Neil Shapiro ** 20140266059SGregory Neil Shapiro ** Sets errno: 20240266059SGregory Neil Shapiro ** any value of errno specified by sm_io_setinfo_type() 20340266059SGregory Neil Shapiro ** any value of errno specified by sm_io_open() 20440266059SGregory Neil Shapiro ** any value of errno specified by sm_io_setinfo() 20540266059SGregory Neil Shapiro */ 20640266059SGregory Neil Shapiro 20794c01205SGregory Neil Shapiro #ifdef __STDC__ 20894c01205SGregory Neil Shapiro /* 20994c01205SGregory Neil Shapiro ** XXX This is a temporary hack since MODE_T on HP-UX 10.x is short. 21094c01205SGregory Neil Shapiro ** If we use K&R here, the compiler will complain about 21194c01205SGregory Neil Shapiro ** Inconsistent parameter list declaration 21294c01205SGregory Neil Shapiro ** due to the change from short to int. 21394c01205SGregory Neil Shapiro */ 21494c01205SGregory Neil Shapiro 21594c01205SGregory Neil Shapiro SM_FILE_T * 21694c01205SGregory Neil Shapiro bfopen(char *filename, MODE_T fmode, size_t bsize, long flags) 21794c01205SGregory Neil Shapiro #else /* __STDC__ */ 21840266059SGregory Neil Shapiro SM_FILE_T * 21940266059SGregory Neil Shapiro bfopen(filename, fmode, bsize, flags) 22040266059SGregory Neil Shapiro char *filename; 22140266059SGregory Neil Shapiro MODE_T fmode; 22240266059SGregory Neil Shapiro size_t bsize; 22340266059SGregory Neil Shapiro long flags; 22494c01205SGregory Neil Shapiro #endif /* __STDC__ */ 22540266059SGregory Neil Shapiro { 22640266059SGregory Neil Shapiro MODE_T omask; 22740266059SGregory Neil Shapiro SM_FILE_T SM_IO_SET_TYPE(vector, BF_FILE_TYPE, sm_bfopen, sm_bfclose, 22840266059SGregory Neil Shapiro sm_bfread, sm_bfwrite, sm_bfseek, sm_bfgetinfo, sm_bfsetinfo, 22940266059SGregory Neil Shapiro SM_TIME_FOREVER); 23040266059SGregory Neil Shapiro struct bf_info info; 23140266059SGregory Neil Shapiro 23240266059SGregory Neil Shapiro /* 23340266059SGregory Neil Shapiro ** Apply current umask to fmode as it may change by the time 23440266059SGregory Neil Shapiro ** the file is actually created. fmode becomes the true 23540266059SGregory Neil Shapiro ** permissions of the file, which OPEN() must obey. 23640266059SGregory Neil Shapiro */ 23740266059SGregory Neil Shapiro 23840266059SGregory Neil Shapiro omask = umask(0); 23940266059SGregory Neil Shapiro fmode &= ~omask; 24040266059SGregory Neil Shapiro (void) umask(omask); 24140266059SGregory Neil Shapiro 24240266059SGregory Neil Shapiro SM_IO_INIT_TYPE(vector, BF_FILE_TYPE, sm_bfopen, sm_bfclose, 24340266059SGregory Neil Shapiro sm_bfread, sm_bfwrite, sm_bfseek, sm_bfgetinfo, sm_bfsetinfo, 24440266059SGregory Neil Shapiro SM_TIME_FOREVER); 24540266059SGregory Neil Shapiro info.bi_filename = filename; 24640266059SGregory Neil Shapiro info.bi_fmode = fmode; 24740266059SGregory Neil Shapiro info.bi_bsize = bsize; 24840266059SGregory Neil Shapiro info.bi_flags = flags; 24940266059SGregory Neil Shapiro 25040266059SGregory Neil Shapiro return sm_io_open(&vector, SM_TIME_DEFAULT, &info, SM_IO_RDWR, NULL); 25140266059SGregory Neil Shapiro } 25240266059SGregory Neil Shapiro 25340266059SGregory Neil Shapiro /* 25440266059SGregory Neil Shapiro ** SM_BFGETINFO -- returns info about an open file pointer 25540266059SGregory Neil Shapiro ** 25640266059SGregory Neil Shapiro ** Parameters: 25740266059SGregory Neil Shapiro ** fp -- file pointer to get info about 25840266059SGregory Neil Shapiro ** what -- type of info to obtain 25940266059SGregory Neil Shapiro ** valp -- thing to return the info in 26040266059SGregory Neil Shapiro */ 26140266059SGregory Neil Shapiro 26240266059SGregory Neil Shapiro static int 26340266059SGregory Neil Shapiro sm_bfgetinfo(fp, what, valp) 26440266059SGregory Neil Shapiro SM_FILE_T *fp; 26540266059SGregory Neil Shapiro int what; 26640266059SGregory Neil Shapiro void *valp; 26740266059SGregory Neil Shapiro { 26840266059SGregory Neil Shapiro struct bf *bfp; 26940266059SGregory Neil Shapiro 27040266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 27140266059SGregory Neil Shapiro switch (what) 27240266059SGregory Neil Shapiro { 27340266059SGregory Neil Shapiro case SM_IO_WHAT_FD: 27440266059SGregory Neil Shapiro return bfp->bf_disk_fd; 275605302a5SGregory Neil Shapiro case SM_IO_WHAT_SIZE: 276605302a5SGregory Neil Shapiro return bfp->bf_size; 27740266059SGregory Neil Shapiro default: 27840266059SGregory Neil Shapiro return -1; 27940266059SGregory Neil Shapiro } 28040266059SGregory Neil Shapiro } 28140266059SGregory Neil Shapiro 28240266059SGregory Neil Shapiro /* 28340266059SGregory Neil Shapiro ** SM_BFCLOSE -- close a buffered file 28440266059SGregory Neil Shapiro ** 28540266059SGregory Neil Shapiro ** Parameters: 28640266059SGregory Neil Shapiro ** fp -- cookie of file to close 28740266059SGregory Neil Shapiro ** 28840266059SGregory Neil Shapiro ** Returns: 28940266059SGregory Neil Shapiro ** 0 to indicate success 29040266059SGregory Neil Shapiro ** 29140266059SGregory Neil Shapiro ** Side Effects: 29240266059SGregory Neil Shapiro ** deletes backing file, sm_frees memory. 29340266059SGregory Neil Shapiro ** 29440266059SGregory Neil Shapiro ** Sets errno: 29540266059SGregory Neil Shapiro ** never. 29640266059SGregory Neil Shapiro */ 29740266059SGregory Neil Shapiro 29840266059SGregory Neil Shapiro static int 29940266059SGregory Neil Shapiro sm_bfclose(fp) 30040266059SGregory Neil Shapiro SM_FILE_T *fp; 30140266059SGregory Neil Shapiro { 30240266059SGregory Neil Shapiro struct bf *bfp; 30340266059SGregory Neil Shapiro 30440266059SGregory Neil Shapiro /* Cast cookie back to correct type */ 30540266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 30640266059SGregory Neil Shapiro 30740266059SGregory Neil Shapiro /* Need to clean up the file */ 30840266059SGregory Neil Shapiro if (bfp->bf_ondisk && !bfp->bf_committed) 30940266059SGregory Neil Shapiro unlink(bfp->bf_filename); 31040266059SGregory Neil Shapiro sm_free(bfp->bf_filename); 31140266059SGregory Neil Shapiro 31240266059SGregory Neil Shapiro if (bfp->bf_disk_fd != -1) 31340266059SGregory Neil Shapiro close(bfp->bf_disk_fd); 31440266059SGregory Neil Shapiro 31540266059SGregory Neil Shapiro /* Need to sm_free the buffer */ 31640266059SGregory Neil Shapiro if (bfp->bf_bufsize > 0) 31740266059SGregory Neil Shapiro sm_free(bfp->bf_buf); 31840266059SGregory Neil Shapiro 31940266059SGregory Neil Shapiro /* Finally, sm_free the structure */ 32040266059SGregory Neil Shapiro sm_free(bfp); 32140266059SGregory Neil Shapiro return 0; 32240266059SGregory Neil Shapiro } 32340266059SGregory Neil Shapiro 32440266059SGregory Neil Shapiro /* 32540266059SGregory Neil Shapiro ** SM_BFREAD -- read a buffered file 32640266059SGregory Neil Shapiro ** 32740266059SGregory Neil Shapiro ** Parameters: 32840266059SGregory Neil Shapiro ** cookie -- cookie of file to read 32940266059SGregory Neil Shapiro ** buf -- buffer to fill 33040266059SGregory Neil Shapiro ** nbytes -- how many bytes to read 33140266059SGregory Neil Shapiro ** 33240266059SGregory Neil Shapiro ** Returns: 33340266059SGregory Neil Shapiro ** number of bytes read or -1 indicate failure 33440266059SGregory Neil Shapiro ** 33540266059SGregory Neil Shapiro ** Side Effects: 33640266059SGregory Neil Shapiro ** none. 33740266059SGregory Neil Shapiro ** 33840266059SGregory Neil Shapiro */ 33940266059SGregory Neil Shapiro 34040266059SGregory Neil Shapiro static ssize_t 34140266059SGregory Neil Shapiro sm_bfread(fp, buf, nbytes) 34240266059SGregory Neil Shapiro SM_FILE_T *fp; 34340266059SGregory Neil Shapiro char *buf; 34440266059SGregory Neil Shapiro size_t nbytes; 34540266059SGregory Neil Shapiro { 34640266059SGregory Neil Shapiro struct bf *bfp; 34740266059SGregory Neil Shapiro ssize_t count = 0; /* Number of bytes put in buf so far */ 34840266059SGregory Neil Shapiro int retval; 34940266059SGregory Neil Shapiro 35040266059SGregory Neil Shapiro /* Cast cookie back to correct type */ 35140266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 35240266059SGregory Neil Shapiro 35340266059SGregory Neil Shapiro if (bfp->bf_offset < bfp->bf_buffilled) 35440266059SGregory Neil Shapiro { 35540266059SGregory Neil Shapiro /* Need to grab some from buffer */ 35640266059SGregory Neil Shapiro count = nbytes; 35740266059SGregory Neil Shapiro if ((bfp->bf_offset + count) > bfp->bf_buffilled) 35840266059SGregory Neil Shapiro count = bfp->bf_buffilled - bfp->bf_offset; 35940266059SGregory Neil Shapiro 36040266059SGregory Neil Shapiro memcpy(buf, bfp->bf_buf + bfp->bf_offset, count); 36140266059SGregory Neil Shapiro } 36240266059SGregory Neil Shapiro 36340266059SGregory Neil Shapiro if ((bfp->bf_offset + nbytes) > bfp->bf_buffilled) 36440266059SGregory Neil Shapiro { 36540266059SGregory Neil Shapiro /* Need to grab some from file */ 36640266059SGregory Neil Shapiro if (!bfp->bf_ondisk) 36740266059SGregory Neil Shapiro { 36840266059SGregory Neil Shapiro /* Oops, the file doesn't exist. EOF. */ 36940266059SGregory Neil Shapiro if (tTd(58, 8)) 37040266059SGregory Neil Shapiro sm_dprintf("sm_bfread(%s): to disk\n", 37140266059SGregory Neil Shapiro bfp->bf_filename); 37240266059SGregory Neil Shapiro goto finished; 37340266059SGregory Neil Shapiro } 37440266059SGregory Neil Shapiro 37540266059SGregory Neil Shapiro /* Catch a read() on an earlier failed write to disk */ 37640266059SGregory Neil Shapiro if (bfp->bf_disk_fd < 0) 37740266059SGregory Neil Shapiro { 37840266059SGregory Neil Shapiro errno = EIO; 37940266059SGregory Neil Shapiro return -1; 38040266059SGregory Neil Shapiro } 38140266059SGregory Neil Shapiro 38240266059SGregory Neil Shapiro if (lseek(bfp->bf_disk_fd, 38340266059SGregory Neil Shapiro bfp->bf_offset + count, SEEK_SET) < 0) 38440266059SGregory Neil Shapiro { 38540266059SGregory Neil Shapiro if ((errno == EINVAL) || (errno == ESPIPE)) 38640266059SGregory Neil Shapiro { 38740266059SGregory Neil Shapiro /* 38840266059SGregory Neil Shapiro ** stdio won't be expecting these 38940266059SGregory Neil Shapiro ** errnos from read()! Change them 39040266059SGregory Neil Shapiro ** into something it can understand. 39140266059SGregory Neil Shapiro */ 39240266059SGregory Neil Shapiro 39340266059SGregory Neil Shapiro errno = EIO; 39440266059SGregory Neil Shapiro } 39540266059SGregory Neil Shapiro return -1; 39640266059SGregory Neil Shapiro } 39740266059SGregory Neil Shapiro 39840266059SGregory Neil Shapiro while (count < nbytes) 39940266059SGregory Neil Shapiro { 40040266059SGregory Neil Shapiro retval = read(bfp->bf_disk_fd, 40140266059SGregory Neil Shapiro buf + count, 40240266059SGregory Neil Shapiro nbytes - count); 40340266059SGregory Neil Shapiro if (retval < 0) 40440266059SGregory Neil Shapiro { 40540266059SGregory Neil Shapiro /* errno is set implicitly by read() */ 40640266059SGregory Neil Shapiro return -1; 40740266059SGregory Neil Shapiro } 40840266059SGregory Neil Shapiro else if (retval == 0) 40940266059SGregory Neil Shapiro goto finished; 41040266059SGregory Neil Shapiro else 41140266059SGregory Neil Shapiro count += retval; 41240266059SGregory Neil Shapiro } 41340266059SGregory Neil Shapiro } 41440266059SGregory Neil Shapiro 41540266059SGregory Neil Shapiro finished: 41640266059SGregory Neil Shapiro bfp->bf_offset += count; 41740266059SGregory Neil Shapiro return count; 41840266059SGregory Neil Shapiro } 41940266059SGregory Neil Shapiro 42040266059SGregory Neil Shapiro /* 42140266059SGregory Neil Shapiro ** SM_BFSEEK -- seek to a position in a buffered file 42240266059SGregory Neil Shapiro ** 42340266059SGregory Neil Shapiro ** Parameters: 42440266059SGregory Neil Shapiro ** fp -- fp of file to seek 42540266059SGregory Neil Shapiro ** offset -- position to seek to 42640266059SGregory Neil Shapiro ** whence -- how to seek 42740266059SGregory Neil Shapiro ** 42840266059SGregory Neil Shapiro ** Returns: 42940266059SGregory Neil Shapiro ** new file offset or -1 indicate failure 43040266059SGregory Neil Shapiro ** 43140266059SGregory Neil Shapiro ** Side Effects: 43240266059SGregory Neil Shapiro ** none. 43340266059SGregory Neil Shapiro ** 43440266059SGregory Neil Shapiro */ 43540266059SGregory Neil Shapiro 43640266059SGregory Neil Shapiro static off_t 43740266059SGregory Neil Shapiro sm_bfseek(fp, offset, whence) 43840266059SGregory Neil Shapiro SM_FILE_T *fp; 43940266059SGregory Neil Shapiro off_t offset; 44040266059SGregory Neil Shapiro int whence; 44140266059SGregory Neil Shapiro 44240266059SGregory Neil Shapiro { 44340266059SGregory Neil Shapiro struct bf *bfp; 44440266059SGregory Neil Shapiro 44540266059SGregory Neil Shapiro /* Cast cookie back to correct type */ 44640266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 44740266059SGregory Neil Shapiro 44840266059SGregory Neil Shapiro switch (whence) 44940266059SGregory Neil Shapiro { 45040266059SGregory Neil Shapiro case SEEK_SET: 45140266059SGregory Neil Shapiro bfp->bf_offset = offset; 45240266059SGregory Neil Shapiro break; 45340266059SGregory Neil Shapiro 45440266059SGregory Neil Shapiro case SEEK_CUR: 45540266059SGregory Neil Shapiro bfp->bf_offset += offset; 45640266059SGregory Neil Shapiro break; 45740266059SGregory Neil Shapiro 45840266059SGregory Neil Shapiro case SEEK_END: 45940266059SGregory Neil Shapiro bfp->bf_offset = bfp->bf_size + offset; 46040266059SGregory Neil Shapiro break; 46140266059SGregory Neil Shapiro 46240266059SGregory Neil Shapiro default: 46340266059SGregory Neil Shapiro errno = EINVAL; 46440266059SGregory Neil Shapiro return -1; 46540266059SGregory Neil Shapiro } 46640266059SGregory Neil Shapiro return bfp->bf_offset; 46740266059SGregory Neil Shapiro } 46840266059SGregory Neil Shapiro 46940266059SGregory Neil Shapiro /* 47040266059SGregory Neil Shapiro ** SM_BFWRITE -- write to a buffered file 47140266059SGregory Neil Shapiro ** 47240266059SGregory Neil Shapiro ** Parameters: 47340266059SGregory Neil Shapiro ** fp -- fp of file to write 47440266059SGregory Neil Shapiro ** buf -- data buffer 47540266059SGregory Neil Shapiro ** nbytes -- how many bytes to write 47640266059SGregory Neil Shapiro ** 47740266059SGregory Neil Shapiro ** Returns: 47840266059SGregory Neil Shapiro ** number of bytes written or -1 indicate failure 47940266059SGregory Neil Shapiro ** 48040266059SGregory Neil Shapiro ** Side Effects: 48140266059SGregory Neil Shapiro ** may create backing file if over memory limit for file. 48240266059SGregory Neil Shapiro ** 48340266059SGregory Neil Shapiro */ 48440266059SGregory Neil Shapiro 48540266059SGregory Neil Shapiro static ssize_t 48640266059SGregory Neil Shapiro sm_bfwrite(fp, buf, nbytes) 48740266059SGregory Neil Shapiro SM_FILE_T *fp; 48840266059SGregory Neil Shapiro const char *buf; 48940266059SGregory Neil Shapiro size_t nbytes; 49040266059SGregory Neil Shapiro { 49140266059SGregory Neil Shapiro struct bf *bfp; 49240266059SGregory Neil Shapiro ssize_t count = 0; /* Number of bytes written so far */ 49340266059SGregory Neil Shapiro int retval; 49440266059SGregory Neil Shapiro 49540266059SGregory Neil Shapiro /* Cast cookie back to correct type */ 49640266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 49740266059SGregory Neil Shapiro 49840266059SGregory Neil Shapiro /* If committed, go straight to disk */ 49940266059SGregory Neil Shapiro if (bfp->bf_committed) 50040266059SGregory Neil Shapiro { 50140266059SGregory Neil Shapiro if (lseek(bfp->bf_disk_fd, bfp->bf_offset, SEEK_SET) < 0) 50240266059SGregory Neil Shapiro { 50340266059SGregory Neil Shapiro if ((errno == EINVAL) || (errno == ESPIPE)) 50440266059SGregory Neil Shapiro { 50540266059SGregory Neil Shapiro /* 50640266059SGregory Neil Shapiro ** stdio won't be expecting these 50740266059SGregory Neil Shapiro ** errnos from write()! Change them 50840266059SGregory Neil Shapiro ** into something it can understand. 50940266059SGregory Neil Shapiro */ 51040266059SGregory Neil Shapiro 51140266059SGregory Neil Shapiro errno = EIO; 51240266059SGregory Neil Shapiro } 51340266059SGregory Neil Shapiro return -1; 51440266059SGregory Neil Shapiro } 51540266059SGregory Neil Shapiro 51640266059SGregory Neil Shapiro count = write(bfp->bf_disk_fd, buf, nbytes); 51740266059SGregory Neil Shapiro if (count < 0) 51840266059SGregory Neil Shapiro { 51940266059SGregory Neil Shapiro /* errno is set implicitly by write() */ 52040266059SGregory Neil Shapiro return -1; 52140266059SGregory Neil Shapiro } 52240266059SGregory Neil Shapiro goto finished; 52340266059SGregory Neil Shapiro } 52440266059SGregory Neil Shapiro 52540266059SGregory Neil Shapiro if (bfp->bf_offset < bfp->bf_bufsize) 52640266059SGregory Neil Shapiro { 52740266059SGregory Neil Shapiro /* Need to put some in buffer */ 52840266059SGregory Neil Shapiro count = nbytes; 52940266059SGregory Neil Shapiro if ((bfp->bf_offset + count) > bfp->bf_bufsize) 53040266059SGregory Neil Shapiro count = bfp->bf_bufsize - bfp->bf_offset; 53140266059SGregory Neil Shapiro 53240266059SGregory Neil Shapiro memcpy(bfp->bf_buf + bfp->bf_offset, buf, count); 53340266059SGregory Neil Shapiro if ((bfp->bf_offset + count) > bfp->bf_buffilled) 53440266059SGregory Neil Shapiro bfp->bf_buffilled = bfp->bf_offset + count; 53540266059SGregory Neil Shapiro } 53640266059SGregory Neil Shapiro 53740266059SGregory Neil Shapiro if ((bfp->bf_offset + nbytes) > bfp->bf_bufsize) 53840266059SGregory Neil Shapiro { 53940266059SGregory Neil Shapiro /* Need to put some in file */ 54040266059SGregory Neil Shapiro if (!bfp->bf_ondisk) 54140266059SGregory Neil Shapiro { 54240266059SGregory Neil Shapiro MODE_T omask; 543af9557fdSGregory Neil Shapiro int save_errno; 54440266059SGregory Neil Shapiro 54540266059SGregory Neil Shapiro /* Clear umask as bf_filemode are the true perms */ 54640266059SGregory Neil Shapiro omask = umask(0); 54740266059SGregory Neil Shapiro retval = OPEN(bfp->bf_filename, 548a7ec597cSGregory Neil Shapiro O_RDWR | O_CREAT | O_TRUNC | QF_O_EXTRA, 54940266059SGregory Neil Shapiro bfp->bf_filemode, bfp->bf_flags); 550af9557fdSGregory Neil Shapiro save_errno = errno; 55140266059SGregory Neil Shapiro (void) umask(omask); 552af9557fdSGregory Neil Shapiro errno = save_errno; 55340266059SGregory Neil Shapiro 55440266059SGregory Neil Shapiro /* Couldn't create file: failure */ 55540266059SGregory Neil Shapiro if (retval < 0) 55640266059SGregory Neil Shapiro { 55740266059SGregory Neil Shapiro /* 55840266059SGregory Neil Shapiro ** stdio may not be expecting these 55940266059SGregory Neil Shapiro ** errnos from write()! Change to 56040266059SGregory Neil Shapiro ** something which it can understand. 56140266059SGregory Neil Shapiro ** Note that ENOSPC and EDQUOT are saved 56240266059SGregory Neil Shapiro ** because they are actually valid for 56340266059SGregory Neil Shapiro ** write(). 56440266059SGregory Neil Shapiro */ 56540266059SGregory Neil Shapiro 56640266059SGregory Neil Shapiro if (!(errno == ENOSPC 56740266059SGregory Neil Shapiro #ifdef EDQUOT 56840266059SGregory Neil Shapiro || errno == EDQUOT 56940266059SGregory Neil Shapiro #endif /* EDQUOT */ 57040266059SGregory Neil Shapiro )) 57140266059SGregory Neil Shapiro errno = EIO; 57240266059SGregory Neil Shapiro 57340266059SGregory Neil Shapiro return -1; 57440266059SGregory Neil Shapiro } 57540266059SGregory Neil Shapiro bfp->bf_disk_fd = retval; 57640266059SGregory Neil Shapiro bfp->bf_ondisk = true; 57740266059SGregory Neil Shapiro } 57840266059SGregory Neil Shapiro 57940266059SGregory Neil Shapiro /* Catch a write() on an earlier failed write to disk */ 58040266059SGregory Neil Shapiro if (bfp->bf_ondisk && bfp->bf_disk_fd < 0) 58140266059SGregory Neil Shapiro { 58240266059SGregory Neil Shapiro errno = EIO; 58340266059SGregory Neil Shapiro return -1; 58440266059SGregory Neil Shapiro } 58540266059SGregory Neil Shapiro 58640266059SGregory Neil Shapiro if (lseek(bfp->bf_disk_fd, 58740266059SGregory Neil Shapiro bfp->bf_offset + count, SEEK_SET) < 0) 58840266059SGregory Neil Shapiro { 58940266059SGregory Neil Shapiro if ((errno == EINVAL) || (errno == ESPIPE)) 59040266059SGregory Neil Shapiro { 59140266059SGregory Neil Shapiro /* 59240266059SGregory Neil Shapiro ** stdio won't be expecting these 59340266059SGregory Neil Shapiro ** errnos from write()! Change them into 59440266059SGregory Neil Shapiro ** something which it can understand. 59540266059SGregory Neil Shapiro */ 59640266059SGregory Neil Shapiro 59740266059SGregory Neil Shapiro errno = EIO; 59840266059SGregory Neil Shapiro } 59940266059SGregory Neil Shapiro return -1; 60040266059SGregory Neil Shapiro } 60140266059SGregory Neil Shapiro 60240266059SGregory Neil Shapiro while (count < nbytes) 60340266059SGregory Neil Shapiro { 60440266059SGregory Neil Shapiro retval = write(bfp->bf_disk_fd, buf + count, 60540266059SGregory Neil Shapiro nbytes - count); 60640266059SGregory Neil Shapiro if (retval < 0) 60740266059SGregory Neil Shapiro { 60840266059SGregory Neil Shapiro /* errno is set implicitly by write() */ 60940266059SGregory Neil Shapiro return -1; 61040266059SGregory Neil Shapiro } 61140266059SGregory Neil Shapiro else 61240266059SGregory Neil Shapiro count += retval; 61340266059SGregory Neil Shapiro } 61440266059SGregory Neil Shapiro } 61540266059SGregory Neil Shapiro 61640266059SGregory Neil Shapiro finished: 61740266059SGregory Neil Shapiro bfp->bf_offset += count; 61840266059SGregory Neil Shapiro if (bfp->bf_offset > bfp->bf_size) 61940266059SGregory Neil Shapiro bfp->bf_size = bfp->bf_offset; 62040266059SGregory Neil Shapiro return count; 62140266059SGregory Neil Shapiro } 62240266059SGregory Neil Shapiro 62340266059SGregory Neil Shapiro /* 62440266059SGregory Neil Shapiro ** BFREWIND -- rewinds the SM_FILE_T * 62540266059SGregory Neil Shapiro ** 62640266059SGregory Neil Shapiro ** Parameters: 62740266059SGregory Neil Shapiro ** fp -- SM_FILE_T * to rewind 62840266059SGregory Neil Shapiro ** 62940266059SGregory Neil Shapiro ** Returns: 63040266059SGregory Neil Shapiro ** 0 on success, -1 on error 63140266059SGregory Neil Shapiro ** 63240266059SGregory Neil Shapiro ** Side Effects: 63394c01205SGregory Neil Shapiro ** rewinds the SM_FILE_T * and puts it into read mode. Normally 63494c01205SGregory Neil Shapiro ** one would bfopen() a file, write to it, then bfrewind() and 63540266059SGregory Neil Shapiro ** fread(). If fp is not a buffered file, this is equivalent to 63640266059SGregory Neil Shapiro ** rewind(). 63740266059SGregory Neil Shapiro ** 63840266059SGregory Neil Shapiro ** Sets errno: 63940266059SGregory Neil Shapiro ** any value of errno specified by sm_io_rewind() 64040266059SGregory Neil Shapiro */ 64140266059SGregory Neil Shapiro 64240266059SGregory Neil Shapiro int 64340266059SGregory Neil Shapiro bfrewind(fp) 64440266059SGregory Neil Shapiro SM_FILE_T *fp; 64540266059SGregory Neil Shapiro { 64640266059SGregory Neil Shapiro (void) sm_io_flush(fp, SM_TIME_DEFAULT); 64740266059SGregory Neil Shapiro sm_io_clearerr(fp); /* quicker just to do it */ 64840266059SGregory Neil Shapiro return sm_io_seek(fp, SM_TIME_DEFAULT, 0, SM_IO_SEEK_SET); 64940266059SGregory Neil Shapiro } 65040266059SGregory Neil Shapiro 65140266059SGregory Neil Shapiro /* 65240266059SGregory Neil Shapiro ** SM_BFCOMMIT -- "commits" the buffered file 65340266059SGregory Neil Shapiro ** 65440266059SGregory Neil Shapiro ** Parameters: 65540266059SGregory Neil Shapiro ** fp -- SM_FILE_T * to commit to disk 65640266059SGregory Neil Shapiro ** 65740266059SGregory Neil Shapiro ** Returns: 65840266059SGregory Neil Shapiro ** 0 on success, -1 on error 65940266059SGregory Neil Shapiro ** 66040266059SGregory Neil Shapiro ** Side Effects: 66140266059SGregory Neil Shapiro ** Forces the given SM_FILE_T * to be written to disk if it is not 66240266059SGregory Neil Shapiro ** already, and ensures that it will be kept after closing. If 66340266059SGregory Neil Shapiro ** fp is not a buffered file, this is a no-op. 66440266059SGregory Neil Shapiro ** 66540266059SGregory Neil Shapiro ** Sets errno: 66640266059SGregory Neil Shapiro ** any value of errno specified by open() 66740266059SGregory Neil Shapiro ** any value of errno specified by write() 66840266059SGregory Neil Shapiro ** any value of errno specified by lseek() 66940266059SGregory Neil Shapiro */ 67040266059SGregory Neil Shapiro 67140266059SGregory Neil Shapiro static int 67240266059SGregory Neil Shapiro sm_bfcommit(fp) 67340266059SGregory Neil Shapiro SM_FILE_T *fp; 67440266059SGregory Neil Shapiro { 67540266059SGregory Neil Shapiro struct bf *bfp; 67640266059SGregory Neil Shapiro int retval; 67740266059SGregory Neil Shapiro int byteswritten; 67840266059SGregory Neil Shapiro 67940266059SGregory Neil Shapiro /* Get associated bf structure */ 68040266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 68140266059SGregory Neil Shapiro 68240266059SGregory Neil Shapiro /* If already committed, noop */ 68340266059SGregory Neil Shapiro if (bfp->bf_committed) 68440266059SGregory Neil Shapiro return 0; 68540266059SGregory Neil Shapiro 68640266059SGregory Neil Shapiro /* Do we need to open a file? */ 68740266059SGregory Neil Shapiro if (!bfp->bf_ondisk) 68840266059SGregory Neil Shapiro { 689739ac4d4SGregory Neil Shapiro int save_errno; 69040266059SGregory Neil Shapiro MODE_T omask; 69140266059SGregory Neil Shapiro struct stat st; 69240266059SGregory Neil Shapiro 69340266059SGregory Neil Shapiro if (tTd(58, 8)) 69440266059SGregory Neil Shapiro { 69540266059SGregory Neil Shapiro sm_dprintf("bfcommit(%s): to disk\n", bfp->bf_filename); 69640266059SGregory Neil Shapiro if (tTd(58, 32)) 69740266059SGregory Neil Shapiro sm_dprintf("bfcommit(): filemode %o flags %ld\n", 69840266059SGregory Neil Shapiro bfp->bf_filemode, bfp->bf_flags); 69940266059SGregory Neil Shapiro } 70040266059SGregory Neil Shapiro 70140266059SGregory Neil Shapiro if (stat(bfp->bf_filename, &st) == 0) 70240266059SGregory Neil Shapiro { 70340266059SGregory Neil Shapiro errno = EEXIST; 70440266059SGregory Neil Shapiro return -1; 70540266059SGregory Neil Shapiro } 70640266059SGregory Neil Shapiro 70740266059SGregory Neil Shapiro /* Clear umask as bf_filemode are the true perms */ 70840266059SGregory Neil Shapiro omask = umask(0); 709e92d3f3fSGregory Neil Shapiro retval = OPEN(bfp->bf_filename, 710e92d3f3fSGregory Neil Shapiro O_RDWR | O_CREAT | O_EXCL | QF_O_EXTRA, 71140266059SGregory Neil Shapiro bfp->bf_filemode, bfp->bf_flags); 712739ac4d4SGregory Neil Shapiro save_errno = errno; 71340266059SGregory Neil Shapiro (void) umask(omask); 71440266059SGregory Neil Shapiro 71540266059SGregory Neil Shapiro /* Couldn't create file: failure */ 71640266059SGregory Neil Shapiro if (retval < 0) 71740266059SGregory Neil Shapiro { 71840266059SGregory Neil Shapiro /* errno is set implicitly by open() */ 719739ac4d4SGregory Neil Shapiro errno = save_errno; 72040266059SGregory Neil Shapiro return -1; 72140266059SGregory Neil Shapiro } 72240266059SGregory Neil Shapiro 72340266059SGregory Neil Shapiro bfp->bf_disk_fd = retval; 72440266059SGregory Neil Shapiro bfp->bf_ondisk = true; 72540266059SGregory Neil Shapiro } 72640266059SGregory Neil Shapiro 72740266059SGregory Neil Shapiro /* Write out the contents of our buffer, if we have any */ 72840266059SGregory Neil Shapiro if (bfp->bf_buffilled > 0) 72940266059SGregory Neil Shapiro { 73040266059SGregory Neil Shapiro byteswritten = 0; 73140266059SGregory Neil Shapiro 73240266059SGregory Neil Shapiro if (lseek(bfp->bf_disk_fd, 0, SEEK_SET) < 0) 73340266059SGregory Neil Shapiro { 73440266059SGregory Neil Shapiro /* errno is set implicitly by lseek() */ 73540266059SGregory Neil Shapiro return -1; 73640266059SGregory Neil Shapiro } 73740266059SGregory Neil Shapiro 73840266059SGregory Neil Shapiro while (byteswritten < bfp->bf_buffilled) 73940266059SGregory Neil Shapiro { 74040266059SGregory Neil Shapiro retval = write(bfp->bf_disk_fd, 74140266059SGregory Neil Shapiro bfp->bf_buf + byteswritten, 74240266059SGregory Neil Shapiro bfp->bf_buffilled - byteswritten); 74340266059SGregory Neil Shapiro if (retval < 0) 74440266059SGregory Neil Shapiro { 74540266059SGregory Neil Shapiro /* errno is set implicitly by write() */ 74640266059SGregory Neil Shapiro return -1; 74740266059SGregory Neil Shapiro } 74840266059SGregory Neil Shapiro else 74940266059SGregory Neil Shapiro byteswritten += retval; 75040266059SGregory Neil Shapiro } 75140266059SGregory Neil Shapiro } 75240266059SGregory Neil Shapiro bfp->bf_committed = true; 75340266059SGregory Neil Shapiro 75440266059SGregory Neil Shapiro /* Invalidate buf; all goes to file now */ 75540266059SGregory Neil Shapiro bfp->bf_buffilled = 0; 75640266059SGregory Neil Shapiro if (bfp->bf_bufsize > 0) 75740266059SGregory Neil Shapiro { 75840266059SGregory Neil Shapiro /* Don't need buffer anymore; free it */ 75940266059SGregory Neil Shapiro bfp->bf_bufsize = 0; 76040266059SGregory Neil Shapiro sm_free(bfp->bf_buf); 76140266059SGregory Neil Shapiro } 76240266059SGregory Neil Shapiro return 0; 76340266059SGregory Neil Shapiro } 76440266059SGregory Neil Shapiro 76540266059SGregory Neil Shapiro /* 76640266059SGregory Neil Shapiro ** SM_BFTRUNCATE -- rewinds and truncates the SM_FILE_T * 76740266059SGregory Neil Shapiro ** 76840266059SGregory Neil Shapiro ** Parameters: 76940266059SGregory Neil Shapiro ** fp -- SM_FILE_T * to truncate 77040266059SGregory Neil Shapiro ** 77140266059SGregory Neil Shapiro ** Returns: 77240266059SGregory Neil Shapiro ** 0 on success, -1 on error 77340266059SGregory Neil Shapiro ** 77440266059SGregory Neil Shapiro ** Side Effects: 77540266059SGregory Neil Shapiro ** rewinds the SM_FILE_T *, truncates it to zero length, and puts 77640266059SGregory Neil Shapiro ** it into write mode. 77740266059SGregory Neil Shapiro ** 77840266059SGregory Neil Shapiro ** Sets errno: 77940266059SGregory Neil Shapiro ** any value of errno specified by fseek() 78040266059SGregory Neil Shapiro ** any value of errno specified by ftruncate() 78140266059SGregory Neil Shapiro */ 78240266059SGregory Neil Shapiro 78340266059SGregory Neil Shapiro static int 78440266059SGregory Neil Shapiro sm_bftruncate(fp) 78540266059SGregory Neil Shapiro SM_FILE_T *fp; 78640266059SGregory Neil Shapiro { 78740266059SGregory Neil Shapiro struct bf *bfp; 78840266059SGregory Neil Shapiro 78940266059SGregory Neil Shapiro if (bfrewind(fp) < 0) 79040266059SGregory Neil Shapiro return -1; 79140266059SGregory Neil Shapiro 79240266059SGregory Neil Shapiro /* Get bf structure */ 79340266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 79440266059SGregory Neil Shapiro bfp->bf_buffilled = 0; 79540266059SGregory Neil Shapiro bfp->bf_size = 0; 79640266059SGregory Neil Shapiro 79740266059SGregory Neil Shapiro /* Need to zero the buffer */ 79840266059SGregory Neil Shapiro if (bfp->bf_bufsize > 0) 79940266059SGregory Neil Shapiro memset(bfp->bf_buf, '\0', bfp->bf_bufsize); 80040266059SGregory Neil Shapiro if (bfp->bf_ondisk) 80140266059SGregory Neil Shapiro { 80240266059SGregory Neil Shapiro #if NOFTRUNCATE 80340266059SGregory Neil Shapiro /* XXX: Not much we can do except rewind it */ 80440266059SGregory Neil Shapiro errno = EINVAL; 80540266059SGregory Neil Shapiro return -1; 80640266059SGregory Neil Shapiro #else /* NOFTRUNCATE */ 80740266059SGregory Neil Shapiro return ftruncate(bfp->bf_disk_fd, 0); 80840266059SGregory Neil Shapiro #endif /* NOFTRUNCATE */ 80940266059SGregory Neil Shapiro } 81040266059SGregory Neil Shapiro return 0; 81140266059SGregory Neil Shapiro } 81240266059SGregory Neil Shapiro 81340266059SGregory Neil Shapiro /* 81440266059SGregory Neil Shapiro ** SM_BFSETINFO -- set/change info for an open file pointer 81540266059SGregory Neil Shapiro ** 81640266059SGregory Neil Shapiro ** Parameters: 81740266059SGregory Neil Shapiro ** fp -- file pointer to get info about 81840266059SGregory Neil Shapiro ** what -- type of info to set/change 81940266059SGregory Neil Shapiro ** valp -- thing to set/change the info to 82040266059SGregory Neil Shapiro ** 82140266059SGregory Neil Shapiro */ 82240266059SGregory Neil Shapiro 82340266059SGregory Neil Shapiro static int 82440266059SGregory Neil Shapiro sm_bfsetinfo(fp, what, valp) 82540266059SGregory Neil Shapiro SM_FILE_T *fp; 82640266059SGregory Neil Shapiro int what; 82740266059SGregory Neil Shapiro void *valp; 82840266059SGregory Neil Shapiro { 82940266059SGregory Neil Shapiro struct bf *bfp; 83040266059SGregory Neil Shapiro int bsize; 83140266059SGregory Neil Shapiro 83240266059SGregory Neil Shapiro /* Get bf structure */ 83340266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie; 83440266059SGregory Neil Shapiro switch (what) 83540266059SGregory Neil Shapiro { 83640266059SGregory Neil Shapiro case SM_BF_SETBUFSIZE: 83740266059SGregory Neil Shapiro bsize = *((int *) valp); 83840266059SGregory Neil Shapiro bfp->bf_bufsize = bsize; 83940266059SGregory Neil Shapiro 84040266059SGregory Neil Shapiro /* A zero bsize is valid, just don't allocate memory */ 84140266059SGregory Neil Shapiro if (bsize > 0) 84240266059SGregory Neil Shapiro { 84340266059SGregory Neil Shapiro bfp->bf_buf = (char *) sm_malloc(bsize); 84440266059SGregory Neil Shapiro if (bfp->bf_buf == NULL) 84540266059SGregory Neil Shapiro { 84640266059SGregory Neil Shapiro bfp->bf_bufsize = 0; 84740266059SGregory Neil Shapiro errno = ENOMEM; 84840266059SGregory Neil Shapiro return -1; 84940266059SGregory Neil Shapiro } 85040266059SGregory Neil Shapiro } 85140266059SGregory Neil Shapiro else 85240266059SGregory Neil Shapiro bfp->bf_buf = NULL; 85340266059SGregory Neil Shapiro return 0; 85440266059SGregory Neil Shapiro case SM_BF_COMMIT: 85540266059SGregory Neil Shapiro return sm_bfcommit(fp); 85640266059SGregory Neil Shapiro case SM_BF_TRUNCATE: 85740266059SGregory Neil Shapiro return sm_bftruncate(fp); 85840266059SGregory Neil Shapiro case SM_BF_TEST: 85940266059SGregory Neil Shapiro return 1; /* always */ 86040266059SGregory Neil Shapiro default: 86140266059SGregory Neil Shapiro errno = EINVAL; 86240266059SGregory Neil Shapiro return -1; 86340266059SGregory Neil Shapiro } 86440266059SGregory Neil Shapiro } 865