00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "includes.h"
00033
00034 #define XBUFSIZE BUFSIZ
00035
00036 static XFILE _x_stdin = { 0, NULL, NULL, XBUFSIZE, 0, O_RDONLY, X_IOFBF, 0 };
00037 static XFILE _x_stdout = { 1, NULL, NULL, XBUFSIZE, 0, O_WRONLY, X_IOLBF, 0 };
00038 static XFILE _x_stderr = { 2, NULL, NULL, 0, 0, O_WRONLY, X_IONBF, 0 };
00039
00040 XFILE *x_stdin = &_x_stdin;
00041 XFILE *x_stdout = &_x_stdout;
00042 XFILE *x_stderr = &_x_stderr;
00043
00044 #define X_FLAG_EOF 1
00045 #define X_FLAG_ERROR 2
00046 #define X_FLAG_EINVAL 3
00047
00048
00049 int x_setvbuf(XFILE *f, char *buf, int mode, size_t size)
00050 {
00051 if (x_fflush(f) != 0) return -1;
00052 if (f->bufused) return -1;
00053
00054
00055 if ((f->open_flags & O_ACCMODE) == O_RDONLY) {
00056 mode = X_IOFBF;
00057 }
00058
00059
00060 SAFE_FREE(f->buf);
00061 f->buf = 0;
00062 f->bufsize = 0;
00063 f->next = NULL;
00064 f->bufused = 0;
00065 f->buftype = mode;
00066
00067 if (f->buftype == X_IONBF) return 0;
00068
00069
00070 if (size == 0) size = XBUFSIZE;
00071
00072 f->bufsize = size;
00073 f->bufused = 0;
00074
00075 return 0;
00076 }
00077
00078
00079 static int x_allocate_buffer(XFILE *f)
00080 {
00081 if (f->buf) return 1;
00082 if (f->bufsize == 0) return 0;
00083 f->buf = (char *)SMB_MALLOC(f->bufsize);
00084 if (!f->buf) return 0;
00085 f->next = f->buf;
00086 return 1;
00087 }
00088
00089
00090
00091
00092
00093
00094 XFILE *x_fopen(const char *fname, int flags, mode_t mode)
00095 {
00096 XFILE *ret;
00097
00098 ret = SMB_MALLOC_P(XFILE);
00099 if (!ret) {
00100 return NULL;
00101 }
00102
00103 memset(ret, 0, sizeof(XFILE));
00104
00105 if ((flags & O_ACCMODE) == O_RDWR) {
00106
00107
00108 SAFE_FREE(ret);
00109 errno = EINVAL;
00110 return NULL;
00111 }
00112
00113 ret->open_flags = flags;
00114
00115 ret->fd = sys_open(fname, flags, mode);
00116 if (ret->fd == -1) {
00117 SAFE_FREE(ret);
00118 return NULL;
00119 }
00120
00121 x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE);
00122
00123 return ret;
00124 }
00125
00126 XFILE *x_fdup(const XFILE *f)
00127 {
00128 XFILE *ret;
00129 int fd;
00130
00131 fd = dup(x_fileno(f));
00132 if (fd < 0) {
00133 return NULL;
00134 }
00135
00136 ret = SMB_CALLOC_ARRAY(XFILE, 1);
00137 if (!ret) {
00138 close(fd);
00139 return NULL;
00140 }
00141
00142 ret->fd = fd;
00143 ret->open_flags = f->open_flags;
00144 x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE);
00145 return ret;
00146 }
00147
00148
00149 int x_fclose(XFILE *f)
00150 {
00151 int ret;
00152
00153
00154 (void)x_fflush(f);
00155
00156 ret = close(f->fd);
00157 f->fd = -1;
00158 if (f->buf) {
00159
00160 memset(f->buf, 0, f->bufsize);
00161 SAFE_FREE(f->buf);
00162 }
00163
00164
00165
00166 if (f != x_stdin && f != x_stdout && f != x_stderr) {
00167 SAFE_FREE(f);
00168 }
00169 return ret;
00170 }
00171
00172
00173 size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f)
00174 {
00175 ssize_t ret;
00176 size_t total=0;
00177
00178
00179 if (f->buftype == X_IONBF ||
00180 (!f->buf && !x_allocate_buffer(f))) {
00181 ret = write(f->fd, p, size*nmemb);
00182 if (ret == -1) return -1;
00183 return ret/size;
00184 }
00185
00186
00187 while (total < size*nmemb) {
00188 size_t n = f->bufsize - f->bufused;
00189 n = MIN(n, (size*nmemb)-total);
00190
00191 if (n == 0) {
00192
00193 if (x_fflush(f) != 0) {
00194 return -1;
00195 }
00196 continue;
00197 }
00198
00199 memcpy(f->buf + f->bufused, total+(const char *)p, n);
00200 f->bufused += n;
00201 total += n;
00202 }
00203
00204
00205
00206 if (f->buftype == X_IOLBF && f->bufused) {
00207 int i;
00208 for (i=(size*nmemb)-1; i>=0; i--) {
00209 if (*(i+(const char *)p) == '\n') {
00210 if (x_fflush(f) != 0) {
00211 return -1;
00212 }
00213 break;
00214 }
00215 }
00216 }
00217
00218 return total/size;
00219 }
00220
00221
00222 int x_vfprintf(XFILE *f, const char *format, va_list ap)
00223 {
00224 char *p;
00225 int len, ret;
00226 va_list ap2;
00227
00228 VA_COPY(ap2, ap);
00229
00230 len = vasprintf(&p, format, ap2);
00231 if (len <= 0) return len;
00232 ret = x_fwrite(p, 1, len, f);
00233 SAFE_FREE(p);
00234 return ret;
00235 }
00236
00237 int x_fprintf(XFILE *f, const char *format, ...)
00238 {
00239 va_list ap;
00240 int ret;
00241
00242 va_start(ap, format);
00243 ret = x_vfprintf(f, format, ap);
00244 va_end(ap);
00245 return ret;
00246 }
00247
00248
00249 int x_fileno(const XFILE *f)
00250 {
00251 return f->fd;
00252 }
00253
00254
00255 int x_fflush(XFILE *f)
00256 {
00257 int ret;
00258
00259 if (f->flags & X_FLAG_ERROR) return -1;
00260
00261 if (f->bufused == 0 || !f->buf) return 0;
00262
00263 if ((f->open_flags & O_ACCMODE) != O_WRONLY) {
00264 errno = EINVAL;
00265 return -1;
00266 }
00267
00268 ret = write(f->fd, f->buf, f->bufused);
00269 if (ret == -1) return -1;
00270
00271 f->bufused -= ret;
00272 if (f->bufused > 0) {
00273 f->flags |= X_FLAG_ERROR;
00274 memmove(f->buf, ret + (char *)f->buf, f->bufused);
00275 return -1;
00276 }
00277
00278 return 0;
00279 }
00280
00281
00282 void x_setbuffer(XFILE *f, char *buf, size_t size)
00283 {
00284 x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size);
00285 }
00286
00287
00288 void x_setbuf(XFILE *f, char *buf)
00289 {
00290 x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE);
00291 }
00292
00293
00294 void x_setlinebuf(XFILE *f)
00295 {
00296 x_setvbuf(f, NULL, X_IOLBF, 0);
00297 }
00298
00299
00300
00301 int x_feof(XFILE *f)
00302 {
00303 if (f->flags & X_FLAG_EOF) return 1;
00304 return 0;
00305 }
00306
00307
00308 int x_ferror(XFILE *f)
00309 {
00310 if (f->flags & X_FLAG_ERROR) return 1;
00311 return 0;
00312 }
00313
00314
00315 static void x_fillbuf(XFILE *f)
00316 {
00317 int n;
00318
00319 if (f->bufused) return;
00320
00321 if (!f->buf && !x_allocate_buffer(f)) return;
00322
00323 n = read(f->fd, f->buf, f->bufsize);
00324 if (n <= 0) return;
00325 f->bufused = n;
00326 f->next = f->buf;
00327 }
00328
00329
00330 int x_fgetc(XFILE *f)
00331 {
00332 int ret;
00333
00334 if (f->flags & (X_FLAG_EOF | X_FLAG_ERROR)) return EOF;
00335
00336 if (f->bufused == 0) x_fillbuf(f);
00337
00338 if (f->bufused == 0) {
00339 f->flags |= X_FLAG_EOF;
00340 return EOF;
00341 }
00342
00343 ret = *(unsigned char *)(f->next);
00344 f->next++;
00345 f->bufused--;
00346 return ret;
00347 }
00348
00349
00350 size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f)
00351 {
00352 size_t total = 0;
00353 while (total < size*nmemb) {
00354 int c = x_fgetc(f);
00355 if (c == EOF) break;
00356 (total+(char *)p)[0] = (char)c;
00357 total++;
00358 }
00359 return total/size;
00360 }
00361
00362
00363 char *x_fgets(char *s, int size, XFILE *stream)
00364 {
00365 char *s0 = s;
00366 int l = size;
00367 while (l>1) {
00368 int c = x_fgetc(stream);
00369 if (c == EOF) break;
00370 *s++ = (char)c;
00371 l--;
00372 if (c == '\n') break;
00373 }
00374 if (l==size || x_ferror(stream)) {
00375 return 0;
00376 }
00377 *s = 0;
00378 return s0;
00379 }
00380
00381
00382
00383 off_t x_tseek(XFILE *f, off_t offset, int whence)
00384 {
00385 if (f->flags & X_FLAG_ERROR)
00386 return -1;
00387
00388
00389
00390 if (whence != SEEK_SET && whence != SEEK_END) {
00391 f->flags |= X_FLAG_EINVAL;
00392 errno = EINVAL;
00393 return -1;
00394 }
00395
00396
00397 switch (f->open_flags & O_ACCMODE) {
00398 case O_RDONLY:
00399 f->bufused = 0;
00400 break;
00401 case O_WRONLY:
00402 if (x_fflush(f) != 0)
00403 return -1;
00404 break;
00405 default:
00406 errno = EINVAL;
00407 return -1;
00408 }
00409
00410 f->flags &= ~X_FLAG_EOF;
00411 return (off_t)sys_lseek(f->fd, offset, whence);
00412 }