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>
214313cc83SGregory 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 */
64*d39bd2c1SGregory Neil Shapiro off_t bf_offset; /* Current 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)
705b0945b5SGregory Neil Shapiro #else
7140266059SGregory Neil Shapiro # define OPEN(fn, omode, cmode, sff) safeopen(fn, omode, cmode, sff)
725b0945b5SGregory Neil Shapiro #endif
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
sm_bfopen(fp,info,flags,rpool)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 *
bfopen(char * filename,MODE_T fmode,size_t bsize,long flags)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
sm_bfgetinfo(fp,what,valp)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
sm_bfclose(fp)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
sm_bfread(fp,buf,nbytes)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
sm_bfseek(fp,offset,whence)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
sm_bfwrite(fp,buf,nbytes)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
5695b0945b5SGregory Neil Shapiro #endif
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
bfrewind(fp)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
sm_bfcommit(fp)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",
698da7d7b9cSGregory Neil Shapiro (unsigned int) bfp->bf_filemode,
699da7d7b9cSGregory Neil Shapiro bfp->bf_flags);
70040266059SGregory Neil Shapiro }
70140266059SGregory Neil Shapiro
70240266059SGregory Neil Shapiro if (stat(bfp->bf_filename, &st) == 0)
70340266059SGregory Neil Shapiro {
70440266059SGregory Neil Shapiro errno = EEXIST;
70540266059SGregory Neil Shapiro return -1;
70640266059SGregory Neil Shapiro }
70740266059SGregory Neil Shapiro
70840266059SGregory Neil Shapiro /* Clear umask as bf_filemode are the true perms */
70940266059SGregory Neil Shapiro omask = umask(0);
710e92d3f3fSGregory Neil Shapiro retval = OPEN(bfp->bf_filename,
711e92d3f3fSGregory Neil Shapiro O_RDWR | O_CREAT | O_EXCL | QF_O_EXTRA,
71240266059SGregory Neil Shapiro bfp->bf_filemode, bfp->bf_flags);
713739ac4d4SGregory Neil Shapiro save_errno = errno;
71440266059SGregory Neil Shapiro (void) umask(omask);
71540266059SGregory Neil Shapiro
71640266059SGregory Neil Shapiro /* Couldn't create file: failure */
71740266059SGregory Neil Shapiro if (retval < 0)
71840266059SGregory Neil Shapiro {
71940266059SGregory Neil Shapiro /* errno is set implicitly by open() */
720739ac4d4SGregory Neil Shapiro errno = save_errno;
72140266059SGregory Neil Shapiro return -1;
72240266059SGregory Neil Shapiro }
72340266059SGregory Neil Shapiro
72440266059SGregory Neil Shapiro bfp->bf_disk_fd = retval;
72540266059SGregory Neil Shapiro bfp->bf_ondisk = true;
72640266059SGregory Neil Shapiro }
72740266059SGregory Neil Shapiro
72840266059SGregory Neil Shapiro /* Write out the contents of our buffer, if we have any */
72940266059SGregory Neil Shapiro if (bfp->bf_buffilled > 0)
73040266059SGregory Neil Shapiro {
73140266059SGregory Neil Shapiro byteswritten = 0;
73240266059SGregory Neil Shapiro
73340266059SGregory Neil Shapiro if (lseek(bfp->bf_disk_fd, 0, SEEK_SET) < 0)
73440266059SGregory Neil Shapiro {
73540266059SGregory Neil Shapiro /* errno is set implicitly by lseek() */
73640266059SGregory Neil Shapiro return -1;
73740266059SGregory Neil Shapiro }
73840266059SGregory Neil Shapiro
73940266059SGregory Neil Shapiro while (byteswritten < bfp->bf_buffilled)
74040266059SGregory Neil Shapiro {
74140266059SGregory Neil Shapiro retval = write(bfp->bf_disk_fd,
74240266059SGregory Neil Shapiro bfp->bf_buf + byteswritten,
74340266059SGregory Neil Shapiro bfp->bf_buffilled - byteswritten);
74440266059SGregory Neil Shapiro if (retval < 0)
74540266059SGregory Neil Shapiro {
74640266059SGregory Neil Shapiro /* errno is set implicitly by write() */
74740266059SGregory Neil Shapiro return -1;
74840266059SGregory Neil Shapiro }
74940266059SGregory Neil Shapiro else
75040266059SGregory Neil Shapiro byteswritten += retval;
75140266059SGregory Neil Shapiro }
75240266059SGregory Neil Shapiro }
75340266059SGregory Neil Shapiro bfp->bf_committed = true;
75440266059SGregory Neil Shapiro
75540266059SGregory Neil Shapiro /* Invalidate buf; all goes to file now */
75640266059SGregory Neil Shapiro bfp->bf_buffilled = 0;
75740266059SGregory Neil Shapiro if (bfp->bf_bufsize > 0)
75840266059SGregory Neil Shapiro {
75940266059SGregory Neil Shapiro /* Don't need buffer anymore; free it */
76040266059SGregory Neil Shapiro bfp->bf_bufsize = 0;
76140266059SGregory Neil Shapiro sm_free(bfp->bf_buf);
76240266059SGregory Neil Shapiro }
76340266059SGregory Neil Shapiro return 0;
76440266059SGregory Neil Shapiro }
76540266059SGregory Neil Shapiro
76640266059SGregory Neil Shapiro /*
76740266059SGregory Neil Shapiro ** SM_BFTRUNCATE -- rewinds and truncates the SM_FILE_T *
76840266059SGregory Neil Shapiro **
76940266059SGregory Neil Shapiro ** Parameters:
77040266059SGregory Neil Shapiro ** fp -- SM_FILE_T * to truncate
77140266059SGregory Neil Shapiro **
77240266059SGregory Neil Shapiro ** Returns:
77340266059SGregory Neil Shapiro ** 0 on success, -1 on error
77440266059SGregory Neil Shapiro **
77540266059SGregory Neil Shapiro ** Side Effects:
77640266059SGregory Neil Shapiro ** rewinds the SM_FILE_T *, truncates it to zero length, and puts
77740266059SGregory Neil Shapiro ** it into write mode.
77840266059SGregory Neil Shapiro **
77940266059SGregory Neil Shapiro ** Sets errno:
78040266059SGregory Neil Shapiro ** any value of errno specified by fseek()
78140266059SGregory Neil Shapiro ** any value of errno specified by ftruncate()
78240266059SGregory Neil Shapiro */
78340266059SGregory Neil Shapiro
78440266059SGregory Neil Shapiro static int
sm_bftruncate(fp)78540266059SGregory Neil Shapiro sm_bftruncate(fp)
78640266059SGregory Neil Shapiro SM_FILE_T *fp;
78740266059SGregory Neil Shapiro {
78840266059SGregory Neil Shapiro struct bf *bfp;
78940266059SGregory Neil Shapiro
79040266059SGregory Neil Shapiro if (bfrewind(fp) < 0)
79140266059SGregory Neil Shapiro return -1;
79240266059SGregory Neil Shapiro
79340266059SGregory Neil Shapiro /* Get bf structure */
79440266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie;
79540266059SGregory Neil Shapiro bfp->bf_buffilled = 0;
79640266059SGregory Neil Shapiro bfp->bf_size = 0;
79740266059SGregory Neil Shapiro
79840266059SGregory Neil Shapiro /* Need to zero the buffer */
79940266059SGregory Neil Shapiro if (bfp->bf_bufsize > 0)
80040266059SGregory Neil Shapiro memset(bfp->bf_buf, '\0', bfp->bf_bufsize);
80140266059SGregory Neil Shapiro if (bfp->bf_ondisk)
80240266059SGregory Neil Shapiro {
80340266059SGregory Neil Shapiro #if NOFTRUNCATE
80440266059SGregory Neil Shapiro /* XXX: Not much we can do except rewind it */
80540266059SGregory Neil Shapiro errno = EINVAL;
80640266059SGregory Neil Shapiro return -1;
8075b0945b5SGregory Neil Shapiro #else
80840266059SGregory Neil Shapiro return ftruncate(bfp->bf_disk_fd, 0);
8095b0945b5SGregory Neil Shapiro #endif
81040266059SGregory Neil Shapiro }
81140266059SGregory Neil Shapiro return 0;
81240266059SGregory Neil Shapiro }
81340266059SGregory Neil Shapiro
81440266059SGregory Neil Shapiro /*
81540266059SGregory Neil Shapiro ** SM_BFSETINFO -- set/change info for an open file pointer
81640266059SGregory Neil Shapiro **
81740266059SGregory Neil Shapiro ** Parameters:
81840266059SGregory Neil Shapiro ** fp -- file pointer to get info about
81940266059SGregory Neil Shapiro ** what -- type of info to set/change
82040266059SGregory Neil Shapiro ** valp -- thing to set/change the info to
82140266059SGregory Neil Shapiro **
82240266059SGregory Neil Shapiro */
82340266059SGregory Neil Shapiro
82440266059SGregory Neil Shapiro static int
sm_bfsetinfo(fp,what,valp)82540266059SGregory Neil Shapiro sm_bfsetinfo(fp, what, valp)
82640266059SGregory Neil Shapiro SM_FILE_T *fp;
82740266059SGregory Neil Shapiro int what;
82840266059SGregory Neil Shapiro void *valp;
82940266059SGregory Neil Shapiro {
83040266059SGregory Neil Shapiro struct bf *bfp;
83140266059SGregory Neil Shapiro int bsize;
83240266059SGregory Neil Shapiro
83340266059SGregory Neil Shapiro /* Get bf structure */
83440266059SGregory Neil Shapiro bfp = (struct bf *) fp->f_cookie;
83540266059SGregory Neil Shapiro switch (what)
83640266059SGregory Neil Shapiro {
83740266059SGregory Neil Shapiro case SM_BF_SETBUFSIZE:
83840266059SGregory Neil Shapiro bsize = *((int *) valp);
83940266059SGregory Neil Shapiro bfp->bf_bufsize = bsize;
84040266059SGregory Neil Shapiro
84140266059SGregory Neil Shapiro /* A zero bsize is valid, just don't allocate memory */
84240266059SGregory Neil Shapiro if (bsize > 0)
84340266059SGregory Neil Shapiro {
84440266059SGregory Neil Shapiro bfp->bf_buf = (char *) sm_malloc(bsize);
84540266059SGregory Neil Shapiro if (bfp->bf_buf == NULL)
84640266059SGregory Neil Shapiro {
84740266059SGregory Neil Shapiro bfp->bf_bufsize = 0;
84840266059SGregory Neil Shapiro errno = ENOMEM;
84940266059SGregory Neil Shapiro return -1;
85040266059SGregory Neil Shapiro }
85140266059SGregory Neil Shapiro }
85240266059SGregory Neil Shapiro else
85340266059SGregory Neil Shapiro bfp->bf_buf = NULL;
85440266059SGregory Neil Shapiro return 0;
85540266059SGregory Neil Shapiro case SM_BF_COMMIT:
85640266059SGregory Neil Shapiro return sm_bfcommit(fp);
85740266059SGregory Neil Shapiro case SM_BF_TRUNCATE:
85840266059SGregory Neil Shapiro return sm_bftruncate(fp);
85940266059SGregory Neil Shapiro case SM_BF_TEST:
86040266059SGregory Neil Shapiro return 1; /* always */
86140266059SGregory Neil Shapiro default:
86240266059SGregory Neil Shapiro errno = EINVAL;
86340266059SGregory Neil Shapiro return -1;
86440266059SGregory Neil Shapiro }
86540266059SGregory Neil Shapiro }
866