00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "defs.h"
00021 #include "bufio.h"
00022
00023 static BUFIO *Bopen_internal(int fd, const char *path, const char *dir)
00024 {
00025 BUFIO *b = NULL;
00026 int flags;
00027
00028 switch (dir[0]) {
00029 case 'r':
00030 flags = O_RDONLY;
00031 break;
00032 case 'w':
00033 flags = O_WRONLY | O_CREAT | O_TRUNC;
00034 break;
00035 default:
00036 errno = EINVAL;
00037 EC_FAIL
00038 }
00039 ec_null( b = calloc(1, sizeof(BUFIO)) )
00040 b->fdopen = path == NULL;
00041 if (b->fdopen)
00042 b->fd = fd;
00043 else
00044 b->fd = open(path, flags, PERM_FILE);
00045 ec_neg1( b->fd )
00046 b->dir = dir[0];
00047 return b;
00048
00049 EC_CLEANUP_BGN
00050 free(b);
00051 return NULL;
00052 EC_CLEANUP_END
00053 }
00054
00055 BUFIO *Bfdopen(int fd, const char *dir)
00056 {
00057 return Bopen_internal(fd, NULL, dir);
00058 }
00059
00060
00061 #if 0
00062 BUFIO *Bopen(const char *path, const char *dir)
00063 {
00064 BUFIO *b = NULL;
00065 int flags;
00066
00067 switch (dir[0]) {
00068 case 'r':
00069 flags = O_RDONLY;
00070 break;
00071 case 'w':
00072 flags = O_WRONLY | O_CREAT | O_TRUNC;
00073 break;
00074 default:
00075 errno = EINVAL;
00076 EC_FAIL
00077 }
00078 ec_null( b = calloc(1, sizeof(BUFIO)) )
00079 ec_neg1( b->fd = open(path, flags, PERM_FILE) )
00080 b->dir = dir[0];
00081 return b;
00082
00083 EC_CLEANUP_BGN
00084 free(b);
00085 return NULL;
00086 EC_CLEANUP_END
00087 }
00088 #else
00089 BUFIO *Bopen(const char *path, const char *dir)
00090 {
00091 return Bopen_internal(-1, path, dir);
00092 }
00093 #endif
00094
00095 static bool readbuf(BUFIO *b)
00096 {
00097 if (b->timeout.tv_sec != 0 || b->timeout.tv_usec != 0) {
00098 fd_set set;
00099
00100 FD_ZERO(&set);
00101 FD_SET(b->fd, &set);
00102 ec_neg1( select(b->fd + 1, &set, NULL, NULL, &b->timeout) )
00103 if (!FD_ISSET(b->fd, &set)) {
00104 errno = ETIMEDOUT;
00105 return false;
00106 }
00107 }
00108 ec_neg1( b->total = read(b->fd, b->buf, sizeof(b->buf)) )
00109 if (b->total == 0) {
00110 errno = 0;
00111 return false;
00112 }
00113 b->next = 0;
00114 return true;
00115
00116 EC_CLEANUP_BGN
00117 return false;
00118 EC_CLEANUP_END
00119 }
00120
00121 static bool writebuf(BUFIO *b)
00122 {
00123 ssize_t n, total;
00124
00125 total = 0;
00126 while (total < b->next) {
00127 ec_neg1( n = write(b->fd, &b->buf[total], b->next - total) )
00128 total += n;
00129 }
00130 b->next = 0;
00131 return true;
00132
00133 EC_CLEANUP_BGN
00134 return false;
00135 EC_CLEANUP_END
00136 }
00137
00138 int Bgetc(BUFIO *b)
00139 {
00140 if (b->next >= b->total)
00141 if (!readbuf(b)) {
00142 if (errno == 0)
00143 return -1;
00144 EC_FAIL
00145 }
00146 return b->buf[b->next++];
00147
00148 EC_CLEANUP_BGN
00149 return -1;
00150 EC_CLEANUP_END
00151 }
00152
00153 bool Bputc(BUFIO *b, int c)
00154 {
00155 b->buf[b->next++] = c;
00156 if (b->next >= sizeof(b->buf))
00157 ec_false( writebuf(b) )
00158 return true;
00159
00160 EC_CLEANUP_BGN
00161 return false;
00162 EC_CLEANUP_END
00163 }
00164
00165 bool Bclose(BUFIO *b)
00166 {
00167 if (b != NULL) {
00168 if (b->dir == 'w')
00169 ec_false( writebuf(b) )
00170 if (!b->fdopen)
00171 ec_neg1( close(b->fd) )
00172 free(b);
00173 }
00174 return true;
00175
00176 EC_CLEANUP_BGN
00177 return false;
00178 EC_CLEANUP_END
00179 }
00180
00181
00182
00183
00184
00185 bool Bgets(BUFIO *b, char *s, size_t smax)
00186 {
00187 int c, i;
00188 bool ok = true;
00189
00190 for (i = 0; i < smax - 1; i++) {
00191 switch (c = Bgetc(b)) {
00192 case '\n':
00193 break;
00194 case -1:
00195 ok = i > 0;
00196 break;
00197 default:
00198 s[i] = (char)c;
00199 continue;
00200 }
00201 break;
00202 }
00203 s[i] = '\0';
00204 return ok;
00205 }
00206
00207 void Bsettimeout(BUFIO *b, struct timeval *timeout)
00208 {
00209 b->timeout = *timeout;
00210 }