Home | History | Annotate | Download | only in stdio
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1988 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     31 
     32 
     33 #define	_LARGEFILE64_SOURCE	1
     34 
     35 #include "lint.h"
     36 #include "file64.h"
     37 #include <stdlib.h>
     38 #include <stdio.h>
     39 #include <sys/types.h>
     40 #include <sys/stat.h>
     41 #include "stdiom.h"
     42 
     43 /*
     44  * If buffer space has been pre-allocated use it otherwise malloc space.
     45  * PUSHBACK causes the base pointer to be bumped forward. At least 4 bytes
     46  * of pushback are required to meet international specifications.
     47  * Extra space at the end of the buffer allows for synchronization problems.
     48  * If malloc() fails stdio bails out; assumption being the system is in trouble.
     49  * Associate a buffer with stream; return NULL on error.
     50  */
     51 Uchar *
     52 _findbuf(FILE *iop)
     53 {
     54 	int fd = GET_FD(iop);
     55 	Uchar *buf;
     56 	int size = BUFSIZ;
     57 	Uchar *endbuf;
     58 	int tty = -1;
     59 
     60 	struct stat64 stbuf;		/* used to get file system block size */
     61 
     62 	if (iop->_flag & _IONBF)	/* need a small buffer, at least */
     63 	{
     64 	trysmall:;
     65 		size = _SMBFSZ - PUSHBACK;
     66 		if (fd < _NFILE)
     67 			buf = _smbuf[fd];
     68 		else if ((buf = (Uchar *)malloc(_SMBFSZ * sizeof (Uchar))) !=
     69 		    NULL)
     70 			iop->_flag |= _IOMYBUF;
     71 	}
     72 #ifndef _STDIO_ALLOCATE
     73 	else if (fd < 2 && (tty = isatty(fd))) {
     74 		buf = (fd == 0) ? _sibuf : _sobuf; /* special buffer */
     75 						/* for std{in,out} */
     76 	}
     77 #endif
     78 	else {
     79 		/*
     80 		 * The operating system can tell us the
     81 		 * right size for a buffer;
     82 		 * avoid 0-size buffers as returned for some
     83 		 * special files (doors)
     84 		 */
     85 		if (fstat64(fd, &stbuf) == 0 && stbuf.st_blksize > 0)
     86 			size = stbuf.st_blksize;
     87 
     88 		if ((buf = (Uchar *)malloc(sizeof (Uchar)*(size+_SMBFSZ))) !=
     89 		    NULL)
     90 			iop->_flag |= _IOMYBUF;
     91 		else
     92 			goto trysmall;
     93 	}
     94 	if (buf == NULL)
     95 		return (NULL); 	/* malloc() failed */
     96 	iop->_base = buf + PUSHBACK;	/* bytes for pushback */
     97 	iop->_ptr = buf + PUSHBACK;
     98 	endbuf = iop->_base + size;
     99 	_setbufend(iop, endbuf);
    100 	if (!(iop->_flag & _IONBF) && ((tty != -1) ? tty : isatty(fd)))
    101 		iop->_flag |= _IOLBF;
    102 	return (endbuf);
    103 }
    104