149150Sbostic /*- 249150Sbostic * Copyright (c) 1982, 1988 The Regents of the University of California. 349150Sbostic * All rights reserved. 449150Sbostic * 549150Sbostic * %sccs.include.proprietary.c% 649150Sbostic * 7*60328Smckusick * @(#)read.c 7.3 (Berkeley) 05/24/93 849150Sbostic */ 949150Sbostic 1049150Sbostic #include <sys/param.h> 11*60328Smckusick #include <stand.att/saio.h> 1249150Sbostic 1349150Sbostic read(fdesc, buf, count) 1449150Sbostic int fdesc, count; 1549150Sbostic char *buf; 1649150Sbostic { 1749150Sbostic register i, size; 1849150Sbostic register struct iob *file; 1949150Sbostic register struct fs *fs; 2049150Sbostic int lbn, off; 2149150Sbostic 2249150Sbostic errno = 0; 2349150Sbostic #ifndef SMALL 2449150Sbostic if (fdesc >= 0 && fdesc <= 2) { 2549150Sbostic i = count; 2649150Sbostic do { 2749150Sbostic *buf = getchar(); 2849150Sbostic } while (--i && *buf++ != '\n'); 2949150Sbostic return (count - i); 3049150Sbostic } 3149150Sbostic #endif 3249150Sbostic fdesc -= 3; 3349150Sbostic if (fdesc < 0 || fdesc >= SOPEN_MAX || 3449150Sbostic ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 3549150Sbostic errno = EBADF; 3649150Sbostic return (-1); 3749150Sbostic } 3849150Sbostic if ((file->i_flgs&F_READ) == 0) { 3949150Sbostic errno = EBADF; 4049150Sbostic return (-1); 4149150Sbostic } 4249150Sbostic #ifndef SMALL 4349150Sbostic if ((file->i_flgs & F_FILE) == 0) { 4449150Sbostic file->i_cc = count; 4549150Sbostic file->i_ma = buf; 4649150Sbostic file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 4749150Sbostic i = devread(file); 4849150Sbostic if (i < 0) 4949150Sbostic errno = file->i_error; 5049150Sbostic else 5149150Sbostic file->i_offset += i; 5249150Sbostic return (i); 5349150Sbostic } 5449150Sbostic #endif 5549150Sbostic if (file->i_offset+count > file->i_ino.di_size) 5649150Sbostic count = file->i_ino.di_size - file->i_offset; 5749150Sbostic if ((i = count) <= 0) 5849150Sbostic return (0); 5949150Sbostic /* 6049150Sbostic * While reading full blocks, do I/O into user buffer. 6149150Sbostic * Anything else uses getc(). 6249150Sbostic */ 6349150Sbostic fs = &file->i_fs; 6449150Sbostic while (i) { 6549150Sbostic off = blkoff(fs, file->i_offset); 6649150Sbostic lbn = lblkno(fs, file->i_offset); 6749150Sbostic size = dblksize(fs, &file->i_ino, lbn); 6849150Sbostic #ifndef SMALL 6949150Sbostic if (off == 0 && size <= i) { 7049150Sbostic file->i_bn = fsbtodb(fs, bmap(file, lbn)) + 7149150Sbostic file->i_boff; 7249150Sbostic file->i_cc = size; 7349150Sbostic file->i_ma = buf; 7449150Sbostic if (devread(file) < 0) { 7549150Sbostic errno = file->i_error; 7649150Sbostic return (-1); 7749150Sbostic } 7849150Sbostic file->i_offset += size; 7949150Sbostic file->i_cc = 0; 8049150Sbostic buf += size; 8149150Sbostic i -= size; 8249150Sbostic } else { 8349150Sbostic #endif 8449150Sbostic size -= off; 8549150Sbostic if (size > i) 8649150Sbostic size = i; 8749150Sbostic i -= size; 8849150Sbostic do { 8949150Sbostic *buf++ = getc(fdesc+3); 9049150Sbostic } while (--size); 9149150Sbostic #ifndef SMALL 9249150Sbostic } 9349150Sbostic #endif 9449150Sbostic } 9549150Sbostic return (count); 9649150Sbostic } 9749150Sbostic 9849150Sbostic getc(fdesc) 9949150Sbostic int fdesc; 10049150Sbostic { 10149150Sbostic register struct iob *io; 10249150Sbostic register struct fs *fs; 10349150Sbostic register char *p; 10449150Sbostic int c, lbn, off, size, diff; 10549150Sbostic 10649150Sbostic 10749150Sbostic #ifndef SMALL 10849150Sbostic if (fdesc >= 0 && fdesc <= 2) 10949150Sbostic return (getchar()); 11049150Sbostic #endif 11149150Sbostic fdesc -= 3; 11249150Sbostic if (fdesc < 0 || fdesc >= SOPEN_MAX || 11349150Sbostic ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 11449150Sbostic errno = EBADF; 11549150Sbostic return (-1); 11649150Sbostic } 11749150Sbostic p = io->i_ma; 11849150Sbostic if (io->i_cc <= 0) { 11949150Sbostic if ((io->i_flgs & F_FILE) != 0) { 12049150Sbostic diff = io->i_ino.di_size - io->i_offset; 12149150Sbostic if (diff <= 0) 12249150Sbostic return (-1); 12349150Sbostic fs = &io->i_fs; 12449150Sbostic lbn = lblkno(fs, io->i_offset); 12549150Sbostic io->i_bn = fsbtodb(fs, bmap(io, lbn)) + io->i_boff; 12649150Sbostic off = blkoff(fs, io->i_offset); 12749150Sbostic size = dblksize(fs, &io->i_ino, lbn); 12849150Sbostic } else { 12949150Sbostic io->i_bn = io->i_offset / DEV_BSIZE + io->i_boff; 13049150Sbostic off = 0; 13149150Sbostic size = DEV_BSIZE; 13249150Sbostic } 13349150Sbostic io->i_ma = io->i_buf; 13449150Sbostic io->i_cc = size; 13549150Sbostic if (devread(io) < 0) { 13649150Sbostic errno = io->i_error; 13749150Sbostic return (-1); 13849150Sbostic } 13949150Sbostic if ((io->i_flgs & F_FILE) != 0) { 14049150Sbostic if (io->i_offset - off + size >= io->i_ino.di_size) 14149150Sbostic io->i_cc = diff + off; 14249150Sbostic io->i_cc -= off; 14349150Sbostic } 14449150Sbostic p = &io->i_buf[off]; 14549150Sbostic } 14649150Sbostic io->i_cc--; 14749150Sbostic io->i_offset++; 14849150Sbostic c = (unsigned)*p++; 14949150Sbostic io->i_ma = p; 15049150Sbostic return (c); 15149150Sbostic } 152