xref: /freebsd/contrib/sendmail/src/bf.c (revision a7ec597c92be37562e4f76e105eeb7a3ba64d81a)
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