|
|
1.1 root 1: /*++
2:
3: This file contains stuff for buffering input and output. We use
4: this buffering to allow us to deal with end-of-media conditions
5: on input or output streams.
6:
7: Warning: at this time, these buffers don't get flushed automatically
8: on exit; bclose() must be called.
9:
10: --*/
11:
12: #include <stdio.h>
13: #include <fcntl.h>
14: #include <errno.h>
15: #include <stdlib.h>
16: #include <unistd.h>
17: #include "buf.h"
18:
19: extern char *progname;
20:
21: static PBUF balloc(void);
22: static void bfree(PBUF);
23:
24: //
25: // Create a new buffer and associate it with a file. If the file
26: // can't be opened, return NULL.
27: //
28: PBUF
29: bopen(const char *file, int mode)
30: {
31: PBUF pb;
32:
33: pb = balloc();
34:
35: if (-1 == (pb->fd = open(file, mode, 0666))) {
36: fprintf(stderr, "%s: open: ", progname);
37: perror(file);
38: exit(1);
39: }
40: pb->mode = mode;
41: pb->count = 0;
42: pb->offset = 0;
43:
44: return pb;
45: }
46:
47: //
48: // Same as bopen, but from a file descriptor.
49: //
50: PBUF
51: bfdopen(int fd, int mode)
52: {
53: PBUF pb;
54:
55: pb = balloc();
56:
57: pb->fd = fd;
58: pb->mode = mode;
59: pb->count = 0;
60: pb->offset = 0;
61:
62: return pb;
63: }
64:
65: void
66: bclose(PBUF pb)
67: {
68: if (pb->mode & O_WRONLY && pb->offset != 0) {
69: bflush(pb);
70: }
71: (void)close(pb->fd);
72: bfree(pb);
73: }
74:
75: int
76: bgetc(PBUF pb)
77: {
78: if (pb->offset == pb->count) {
79: bfill(pb);
80: }
81:
82: // We don't worry about reaching EOF here; the caller has to
83: // know how many bytes are available and read only that many,
84:
85: return pb->data[pb->offset++];
86: }
87:
88: void
89: bputc(PBUF pb, int c)
90: {
91: pb->data[pb->offset++] = (char)c;
92: if (++pb->count >= sizeof(pb->data)) {
93: bflush(pb);
94: }
95: }
96:
97: //
98: // Set a buffer back to the beginning; that is, the next character
99: // read will be the first one. Could be used on write buffers as well,
100: // but not as likely.
101: //
102: void
103: brewind(PBUF pb)
104: {
105: pb->offset = 0;
106: }
107:
108: //
109: // balloc --
110: // Allocate and initialize a buffer. A pointer to the new buffer
111: // is returned. We set fd to -1 to help find out if people are
112: // writing to a buffer before opening it.
113: //
114: static PBUF
115: balloc()
116: {
117: PBUF pb;
118:
119: if (NULL == (pb = malloc(sizeof(BUF)))) {
120: fprintf(stderr, "%s: malloc: virtual memory exhausted\n",
121: progname);
122: exit(4);
123: }
124: return pb;
125: }
126:
127: static void
128: bfree(PBUF pb)
129: {
130: free(pb);
131: }
132:
133: //
134: // write the contents of a buffer, dealing with end-of-media, if necessary.
135: //
136: void
137: bflush(PBUF pb)
138: {
139: int nbyte;
140:
141: nbyte = write(pb->fd, pb->data, sizeof(pb->data));
142: if (-1 == nbyte) {
143: if (ENOSPC == errno) {
144: // end-of-media; do something about it.
145: } else {
146: fprintf(stderr, "%s: ", progname);
147: perror("write");
148: exit(1);
149: }
150: }
151: pb->count = 0;
152: pb->offset = 0;
153: }
154:
155: //
156: // fill a buffer with data, dealing with end-of-media, if necessary.
157: //
158: void
159: bfill(PBUF pb)
160: {
161: int nbyte;
162:
163: nbyte = read(pb->fd, pb->data, sizeof(pb->data));
164: if (-1 == nbyte) {
165: fprintf(stderr, "%s: ", progname);
166: perror("read");
167: exit(2);
168: }
169: if (0 == nbyte) {
170: // we have reached the end of file. Give user opportunity
171: // to replace the media, and fill the rest of this
172: // buffer XXX.mjb
173: return;
174: }
175: pb->count = nbyte;
176: pb->offset = 0;
177: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.