read.c revision 136093
138032Speter/*	$NetBSD: read.c,v 1.8 1997/01/22 00:38:12 cgd Exp $	*/
2244833Sgshapiro
364562Sgshapiro/*-
438032Speter * Copyright (c) 1993
538032Speter *	The Regents of the University of California.  All rights reserved.
638032Speter *
738032Speter * This code is derived from software contributed to Berkeley by
838032Speter * The Mach Operating System project at Carnegie-Mellon University.
938032Speter *
1038032Speter * Redistribution and use in source and binary forms, with or without
1138032Speter * modification, are permitted provided that the following conditions
1238032Speter * are met:
1338032Speter * 1. Redistributions of source code must retain the above copyright
1464562Sgshapiro *    notice, this list of conditions and the following disclaimer.
15147078Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright
1664562Sgshapiro *    notice, this list of conditions and the following disclaimer in the
17249729Sgshapiro *    documentation and/or other materials provided with the distribution.
1838032Speter * 3. All advertising materials mentioning features or use of this software
1990792Sgshapiro *    must display the following acknowledgement:
2038032Speter *	This product includes software developed by the University of
2190792Sgshapiro *	California, Berkeley and its contributors.
2290792Sgshapiro * 4. Neither the name of the University nor the names of its contributors
2390792Sgshapiro *    may be used to endorse or promote products derived from this software
24120256Sgshapiro *    without specific prior written permission.
2590792Sgshapiro *
26125820Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27125820Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28125820Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29125820Sgshapiro * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30125820Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31125820Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32120256Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33125820Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34125820Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35125820Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36125820Sgshapiro * SUCH DAMAGE.
3790792Sgshapiro *
3890792Sgshapiro *	@(#)read.c	8.1 (Berkeley) 6/11/93
39120256Sgshapiro *
40120256Sgshapiro *
41132943Sgshapiro * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
42132943Sgshapiro * All Rights Reserved.
43132943Sgshapiro *
4490792Sgshapiro * Author: Alessandro Forin
4590792Sgshapiro *
46132943Sgshapiro * Permission to use, copy, modify and distribute this software and its
47132943Sgshapiro * documentation is hereby granted, provided that both the copyright
4890792Sgshapiro * notice and this permission notice appear in all copies of the
4990792Sgshapiro * software, derivative works or modified versions, and any portions
5064562Sgshapiro * thereof, and that both notices appear in supporting documentation.
5190792Sgshapiro *
5290792Sgshapiro * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
5338032Speter * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
5438032Speter * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
5538032Speter *
5638032Speter * Carnegie Mellon requests users of this software to return to
5738032Speter *
5838032Speter *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
5938032Speter *  School of Computer Science
6038032Speter *  Carnegie Mellon University
6138032Speter *  Pittsburgh PA 15213-3890
6238032Speter *
6338032Speter * any improvements or extensions that they make and grant Carnegie the
6490792Sgshapiro * rights to redistribute these changes.
6590792Sgshapiro */
6690792Sgshapiro
6790792Sgshapiro#include <sys/cdefs.h>
6838032Speter__FBSDID("$FreeBSD: head/lib/libstand/read.c 136093 2004-10-03 15:58:20Z stefanf $");
6938032Speter
7038032Speter#include <sys/param.h>
7138032Speter#include "stand.h"
7238032Speter
7390792Sgshapirossize_t
7490792Sgshapiroread(int fd, void *dest, size_t bcount)
75120256Sgshapiro{
7638032Speter    struct open_file	*f = &files[fd];
77120256Sgshapiro    size_t		resid;
78120256Sgshapiro
79120256Sgshapiro    if ((unsigned)fd >= SOPEN_MAX || !(f->f_flags & F_READ)) {
80120256Sgshapiro	errno = EBADF;
81120256Sgshapiro	return (-1);
82120256Sgshapiro    }
83120256Sgshapiro    if (f->f_flags & F_RAW) {
84120256Sgshapiro	twiddle();
85120256Sgshapiro	errno = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
86120256Sgshapiro					btodb(f->f_offset), bcount, dest, &resid);
87120256Sgshapiro	if (errno)
88120256Sgshapiro	    return (-1);
89120256Sgshapiro	f->f_offset += resid;
90120256Sgshapiro	return (resid);
9190792Sgshapiro    }
9294334Sgshapiro
9394334Sgshapiro    /*
9490792Sgshapiro     * Optimise reads from regular files using a readahead buffer.
9590792Sgshapiro     * If the request can't be satisfied from the current buffer contents,
96111823Sgshapiro     * check to see if it should be bypassed, or refill the buffer and complete
9790792Sgshapiro     * the request.
9890792Sgshapiro     */
9990792Sgshapiro    resid = bcount;
10090792Sgshapiro    for (;;) {
10190792Sgshapiro	size_t	ccount, cresid;
10290792Sgshapiro	/* how much can we supply? */
10390792Sgshapiro	ccount = imin(f->f_ralen, resid);
10490792Sgshapiro	if (ccount > 0) {
10590792Sgshapiro	    bcopy(f->f_rabuf + f->f_raoffset, dest, ccount);
10690792Sgshapiro	    f->f_raoffset += ccount;
10790792Sgshapiro	    f->f_ralen -= ccount;
10890792Sgshapiro	    resid -= ccount;
10990792Sgshapiro	    if (resid == 0)
11090792Sgshapiro		return(bcount);
11190792Sgshapiro	    dest = (char *)dest + ccount;
11290792Sgshapiro	}
11390792Sgshapiro
11490792Sgshapiro	/* will filling the readahead buffer again not help? */
11590792Sgshapiro	if (resid >= SOPEN_RASIZE) {
11690792Sgshapiro	    /* bypass the rest of the request and leave the buffer empty */
11790792Sgshapiro	    if ((errno = (f->f_ops->fo_read)(f, dest, resid, &cresid)))
11890792Sgshapiro		    return (-1);
11990792Sgshapiro	    return(bcount - cresid);
12090792Sgshapiro	}
12190792Sgshapiro
12290792Sgshapiro	/* fetch more data */
12390792Sgshapiro	if ((errno = (f->f_ops->fo_read)(f, f->f_rabuf, SOPEN_RASIZE, &cresid)))
12490792Sgshapiro	    return (-1);
12590792Sgshapiro	f->f_raoffset = 0;
12690792Sgshapiro	f->f_ralen = SOPEN_RASIZE - cresid;
12790792Sgshapiro	/* no more data, return what we had */
12890792Sgshapiro	if (f->f_ralen == 0)
12990792Sgshapiro	    return(bcount - resid);
13090792Sgshapiro    }
13190792Sgshapiro}
13290792Sgshapiro