makebuf.c revision 266692
190792Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 16266692SgshapiroSM_RCSID("@(#)$Id: makebuf.c,v 1.27 2013-11-22 20:51:43 ca Exp $") 1790792Sgshapiro#include <stdlib.h> 1890792Sgshapiro#include <unistd.h> 1990792Sgshapiro#include <sys/types.h> 2090792Sgshapiro#include <sys/stat.h> 2190792Sgshapiro#include <sm/io.h> 2290792Sgshapiro#include <sm/heap.h> 2390792Sgshapiro#include <sm/conf.h> 2490792Sgshapiro#include "local.h" 2590792Sgshapiro 2690792Sgshapiro/* 2790792Sgshapiro** SM_MAKEBUF -- make a buffer for the file 2890792Sgshapiro** 2990792Sgshapiro** Parameters: 3090792Sgshapiro** fp -- the file to be buffered 3190792Sgshapiro** 3290792Sgshapiro** Returns: 3390792Sgshapiro** nothing 3490792Sgshapiro** 3590792Sgshapiro** Allocate a file buffer, or switch to unbuffered I/O. 3690792Sgshapiro** By default tty devices default to line buffered. 3790792Sgshapiro*/ 3890792Sgshapiro 3990792Sgshapirovoid 4090792Sgshapirosm_makebuf(fp) 4190792Sgshapiro register SM_FILE_T *fp; 4290792Sgshapiro{ 4390792Sgshapiro register void *p; 4490792Sgshapiro register int flags; 4590792Sgshapiro size_t size; 4690792Sgshapiro int couldbetty; 4790792Sgshapiro 4890792Sgshapiro if (fp->f_flags & SMNBF) 4990792Sgshapiro { 5090792Sgshapiro fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 5190792Sgshapiro fp->f_bf.smb_size = 1; 5290792Sgshapiro return; 5390792Sgshapiro } 5490792Sgshapiro flags = sm_whatbuf(fp, &size, &couldbetty); 5590792Sgshapiro if ((p = sm_malloc(size)) == NULL) 5690792Sgshapiro { 5790792Sgshapiro fp->f_flags |= SMNBF; 5890792Sgshapiro fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; 5990792Sgshapiro fp->f_bf.smb_size = 1; 6090792Sgshapiro return; 6190792Sgshapiro } 6290792Sgshapiro if (!Sm_IO_DidInit) 6390792Sgshapiro sm_init(); 6490792Sgshapiro flags |= SMMBF; 6590792Sgshapiro fp->f_bf.smb_base = fp->f_p = p; 6690792Sgshapiro fp->f_bf.smb_size = size; 6790792Sgshapiro if (couldbetty && isatty(fp->f_file)) 6890792Sgshapiro flags |= SMLBF; 6990792Sgshapiro fp->f_flags |= flags; 7090792Sgshapiro} 7190792Sgshapiro 7290792Sgshapiro/* 7390792Sgshapiro** SM_WHATBUF -- determine proper buffer for a file (internal) 7490792Sgshapiro** 7590792Sgshapiro** Plus it fills in 'bufsize' for recommended buffer size and 7690792Sgshapiro** fills in flag to indicate if 'fp' could be a tty (nothing 7790792Sgshapiro** to do with "betty" :-) ). 7890792Sgshapiro** 7990792Sgshapiro** Parameters: 8090792Sgshapiro** fp -- file pointer to be buffered 8190792Sgshapiro** bufsize -- new buffer size (a return) 8290792Sgshapiro** couldbetty -- could be a tty (returns) 8390792Sgshapiro** 8490792Sgshapiro** Returns: 8590792Sgshapiro** Success: 8690792Sgshapiro** on error: 8790792Sgshapiro** SMNPT -- not seek opimized 8890792Sgshapiro** SMOPT -- seek opimized 8990792Sgshapiro*/ 9090792Sgshapiro 9190792Sgshapiroint 9290792Sgshapirosm_whatbuf(fp, bufsize, couldbetty) 9390792Sgshapiro register SM_FILE_T *fp; 9490792Sgshapiro size_t *bufsize; 9590792Sgshapiro int *couldbetty; 9690792Sgshapiro{ 9790792Sgshapiro struct stat st; 9890792Sgshapiro 9990792Sgshapiro if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) 10090792Sgshapiro { 10190792Sgshapiro *couldbetty = 0; 10290792Sgshapiro *bufsize = SM_IO_BUFSIZ; 10390792Sgshapiro return SMNPT; 10490792Sgshapiro } 10590792Sgshapiro 10690792Sgshapiro /* could be a tty iff it is a character device */ 10790792Sgshapiro *couldbetty = S_ISCHR(st.st_mode); 10890792Sgshapiro if (st.st_blksize == 0) 10990792Sgshapiro { 11090792Sgshapiro *bufsize = SM_IO_BUFSIZ; 11190792Sgshapiro return SMNPT; 11290792Sgshapiro } 11390792Sgshapiro 11490792Sgshapiro#if SM_IO_MAX_BUF_FILE > 0 11590792Sgshapiro if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) 11690792Sgshapiro st.st_blksize = SM_IO_MAX_BUF_FILE; 11790792Sgshapiro#endif /* SM_IO_MAX_BUF_FILE > 0 */ 11890792Sgshapiro 11990792Sgshapiro#if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 12090792Sgshapiro if (!S_ISREG(st.st_mode)) 12190792Sgshapiro { 12290792Sgshapiro# if SM_IO_MAX_BUF > 0 12390792Sgshapiro if (st.st_blksize > SM_IO_MAX_BUF) 12490792Sgshapiro st.st_blksize = SM_IO_MAX_BUF; 12590792Sgshapiro# if SM_IO_MIN_BUF > 0 12690792Sgshapiro else 12790792Sgshapiro# endif /* SM_IO_MIN_BUF > 0 */ 12890792Sgshapiro# endif /* SM_IO_MAX_BUF > 0 */ 12990792Sgshapiro# if SM_IO_MIN_BUF > 0 13090792Sgshapiro if (st.st_blksize < SM_IO_MIN_BUF) 13190792Sgshapiro st.st_blksize = SM_IO_MIN_BUF; 13290792Sgshapiro# endif /* SM_IO_MIN_BUF > 0 */ 13390792Sgshapiro } 13490792Sgshapiro#endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ 13590792Sgshapiro 13690792Sgshapiro /* 13790792Sgshapiro ** Optimise fseek() only if it is a regular file. (The test for 13890792Sgshapiro ** sm_std_seek is mainly paranoia.) It is safe to set _blksize 13990792Sgshapiro ** unconditionally; it will only be used if SMOPT is also set. 14090792Sgshapiro */ 14190792Sgshapiro 14290792Sgshapiro if ((fp->f_flags & SMSTR) == 0) 14390792Sgshapiro { 14490792Sgshapiro *bufsize = st.st_blksize; 14590792Sgshapiro fp->f_blksize = st.st_blksize; 14690792Sgshapiro } 14790792Sgshapiro else 14890792Sgshapiro *bufsize = SM_IO_BUFSIZ; 14990792Sgshapiro if ((st.st_mode & S_IFMT) == S_IFREG && 15090792Sgshapiro fp->f_seek == sm_stdseek) 15190792Sgshapiro return SMOPT; 15290792Sgshapiro else 15390792Sgshapiro return SMNPT; 15490792Sgshapiro} 155