|
|
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 (sizeof(pb->data) == ++pb->count) { ! 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.