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