xref: /original-bsd/sys/stand.att/read.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1982, 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  *
7  *	@(#)read.c	8.1 (Berkeley) 06/11/93
8  */
9 
10 #include <sys/param.h>
11 #include <stand.att/saio.h>
12 
13 read(fdesc, buf, count)
14 	int fdesc, count;
15 	char *buf;
16 {
17 	register i, size;
18 	register struct iob *file;
19 	register struct fs *fs;
20 	int lbn, off;
21 
22 	errno = 0;
23 #ifndef SMALL
24 	if (fdesc >= 0 && fdesc <= 2) {
25 		i = count;
26 		do {
27 			*buf = getchar();
28 		} while (--i && *buf++ != '\n');
29 		return (count - i);
30 	}
31 #endif
32 	fdesc -= 3;
33 	if (fdesc < 0 || fdesc >= SOPEN_MAX ||
34 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
35 		errno = EBADF;
36 		return (-1);
37 	}
38 	if ((file->i_flgs&F_READ) == 0) {
39 		errno = EBADF;
40 		return (-1);
41 	}
42 #ifndef SMALL
43 	if ((file->i_flgs & F_FILE) == 0) {
44 		file->i_cc = count;
45 		file->i_ma = buf;
46 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
47 		i = devread(file);
48 		if (i < 0)
49 			errno = file->i_error;
50 		else
51 			file->i_offset += i;
52 		return (i);
53 	}
54 #endif
55 	if (file->i_offset+count > file->i_ino.di_size)
56 		count = file->i_ino.di_size - file->i_offset;
57 	if ((i = count) <= 0)
58 		return (0);
59 	/*
60 	 * While reading full blocks, do I/O into user buffer.
61 	 * Anything else uses getc().
62 	 */
63 	fs = &file->i_fs;
64 	while (i) {
65 		off = blkoff(fs, file->i_offset);
66 		lbn = lblkno(fs, file->i_offset);
67 		size = dblksize(fs, &file->i_ino, lbn);
68 #ifndef SMALL
69 		if (off == 0 && size <= i) {
70 			file->i_bn = fsbtodb(fs, bmap(file, lbn)) +
71 			    file->i_boff;
72 			file->i_cc = size;
73 			file->i_ma = buf;
74 			if (devread(file) < 0) {
75 				errno = file->i_error;
76 				return (-1);
77 			}
78 			file->i_offset += size;
79 			file->i_cc = 0;
80 			buf += size;
81 			i -= size;
82 		} else {
83 #endif
84 			size -= off;
85 			if (size > i)
86 				size = i;
87 			i -= size;
88 			do {
89 				*buf++ = getc(fdesc+3);
90 			} while (--size);
91 #ifndef	SMALL
92 		}
93 #endif
94 	}
95 	return (count);
96 }
97 
98 getc(fdesc)
99 	int fdesc;
100 {
101 	register struct iob *io;
102 	register struct fs *fs;
103 	register char *p;
104 	int c, lbn, off, size, diff;
105 
106 
107 #ifndef SMALL
108 	if (fdesc >= 0 && fdesc <= 2)
109 		return (getchar());
110 #endif
111 	fdesc -= 3;
112 	if (fdesc < 0 || fdesc >= SOPEN_MAX ||
113 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
114 		errno = EBADF;
115 		return (-1);
116 	}
117 	p = io->i_ma;
118 	if (io->i_cc <= 0) {
119 		if ((io->i_flgs & F_FILE) != 0) {
120 			diff = io->i_ino.di_size - io->i_offset;
121 			if (diff <= 0)
122 				return (-1);
123 			fs = &io->i_fs;
124 			lbn = lblkno(fs, io->i_offset);
125 			io->i_bn = fsbtodb(fs, bmap(io, lbn)) + io->i_boff;
126 			off = blkoff(fs, io->i_offset);
127 			size = dblksize(fs, &io->i_ino, lbn);
128 		} else {
129 			io->i_bn = io->i_offset / DEV_BSIZE + io->i_boff;
130 			off = 0;
131 			size = DEV_BSIZE;
132 		}
133 		io->i_ma = io->i_buf;
134 		io->i_cc = size;
135 		if (devread(io) < 0) {
136 			errno = io->i_error;
137 			return (-1);
138 		}
139 		if ((io->i_flgs & F_FILE) != 0) {
140 			if (io->i_offset - off + size >= io->i_ino.di_size)
141 				io->i_cc = diff + off;
142 			io->i_cc -= off;
143 		}
144 		p = &io->i_buf[off];
145 	}
146 	io->i_cc--;
147 	io->i_offset++;
148 	c = (unsigned)*p++;
149 	io->i_ma = p;
150 	return (c);
151 }
152