Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
2.9 KiB

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