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
00033
00034
00035
00036
00037
00038 #include <config.h>
00039
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #ifdef HAVE_UNISTD_H
00044 #include <unistd.h>
00045 #endif
00046 #include <assert.h>
00047
00048 #include "pio.h"
00049 #include "err.h"
00050 #include "ckd_alloc.h"
00051
00052 FILE *
00053 fopen_comp(const char *file, const char *mode, int32 * ispipe)
00054 {
00055 FILE *fp;
00056
00057 #ifndef HAVE_POPEN
00058 *ispipe = 0;
00059 #else
00060 int32 k, isgz;
00061 k = strlen(file);
00062 #if defined(WIN32)
00063 *ispipe = (k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00064 || (strcmp(file + k - 3, ".GZ") == 0));
00065 isgz = *ispipe;
00066 #else
00067 *ispipe = 0;
00068 isgz = 0;
00069 if ((k > 2)
00070 && ((strcmp(file + k - 2, ".Z") == 0)
00071 || (strcmp(file + k - 2, ".z") == 0))) {
00072 *ispipe = 1;
00073 }
00074 else {
00075 if ((k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00076 || (strcmp(file + k - 3, ".GZ") == 0))) {
00077 *ispipe = 1;
00078 isgz = 1;
00079 }
00080 }
00081 #endif
00082 #endif
00083
00084 if (*ispipe) {
00085 #ifndef HAVE_POPEN
00086
00087 E_FATAL("No popen() on WinCE\n");
00088 #else
00089 char command[16384];
00090 #if defined(WIN32)
00091 if (strcmp(mode, "r") == 0) {
00092 sprintf(command, "gzip.exe -d -c %s", file);
00093 if ((fp = _popen(command, mode)) == NULL) {
00094 E_ERROR_SYSTEM("_popen (%s,%s) failed\n", command, mode);
00095 return NULL;
00096 }
00097 }
00098 else if (strcmp(mode, "w") == 0) {
00099 sprintf(command, "gzip.exe > %s", file);
00100
00101 if ((fp = _popen(command, mode)) == NULL) {
00102 E_ERROR_SYSTEM("_popen (%s,%s) failed\n", command, mode);
00103 return NULL;
00104 }
00105 }
00106 else {
00107 E_ERROR("fopen_comp not implemented for mode = %s\n", mode);
00108 return NULL;
00109 }
00110 #else
00111 if (strcmp(mode, "r") == 0) {
00112 if (isgz)
00113 sprintf(command, "gunzip -c %s", file);
00114 else
00115 sprintf(command, "zcat %s", file);
00116
00117 if ((fp = popen(command, mode)) == NULL) {
00118 E_ERROR_SYSTEM("popen (%s,%s) failed\n", command, mode);
00119 return NULL;
00120 }
00121 }
00122 else if (strcmp(mode, "w") == 0) {
00123 if (isgz)
00124 sprintf(command, "gzip > %s", file);
00125 else
00126 sprintf(command, "compress -c > %s", file);
00127
00128 if ((fp = popen(command, mode)) == NULL) {
00129 E_ERROR_SYSTEM("popen (%s,%s) failed\n", command, mode);
00130 return NULL;
00131 }
00132 }
00133 else {
00134 E_ERROR("fopen_comp not implemented for mode = %s\n", mode);
00135 return NULL;
00136 }
00137 #endif
00138 #endif
00139 }
00140 else {
00141 fp = fopen(file, mode);
00142 }
00143
00144 return (fp);
00145 }
00146
00147
00148 void
00149 fclose_comp(FILE * fp, int32 ispipe)
00150 {
00151 if (ispipe) {
00152 #ifdef HAVE_POPEN
00153 #if defined(WIN32)
00154 _pclose(fp);
00155 #else
00156 pclose(fp);
00157 #endif
00158 #endif
00159 }
00160 else
00161 fclose(fp);
00162 }
00163
00164
00165 FILE *
00166 fopen_compchk(const char *file, int32 * ispipe)
00167 {
00168 #ifndef HAVE_POPEN
00169 *ispipe = 0;
00170
00171 return (fopen_comp(file, "r", ispipe));
00172 #else
00173 char tmpfile[16384];
00174 int32 k, isgz;
00175 struct stat statbuf;
00176
00177 k = strlen(file);
00178
00179 #if defined(WIN32)
00180 *ispipe = (k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00181 || (strcmp(file + k - 3, ".GZ") == 0));
00182 isgz = *ispipe;
00183 #else
00184 *ispipe = 0;
00185 isgz = 0;
00186 if ((k > 2)
00187 && ((strcmp(file + k - 2, ".Z") == 0)
00188 || (strcmp(file + k - 2, ".z") == 0))) {
00189 *ispipe = 1;
00190 }
00191 else {
00192 if ((k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00193 || (strcmp(file + k - 3, ".GZ") == 0))) {
00194 *ispipe = 1;
00195 isgz = 1;
00196 }
00197 }
00198 #endif
00199
00200 strcpy(tmpfile, file);
00201 if (stat(tmpfile, &statbuf) != 0) {
00202
00203 E_ERROR_SYSTEM("stat(%s) failed\n", tmpfile);
00204
00205 if (*ispipe) {
00206 if (isgz)
00207 tmpfile[k - 3] = '\0';
00208 else
00209 tmpfile[k - 2] = '\0';
00210
00211 if (stat(tmpfile, &statbuf) != 0)
00212 return NULL;
00213 }
00214 else {
00215 strcpy(tmpfile + k, ".gz");
00216 if (stat(tmpfile, &statbuf) != 0) {
00217 #if (! WIN32)
00218 strcpy(tmpfile + k, ".Z");
00219 if (stat(tmpfile, &statbuf) != 0)
00220 return NULL;
00221 #else
00222 return NULL;
00223 #endif
00224 }
00225 }
00226
00227 E_WARN("Using %s instead of %s\n", tmpfile, file);
00228 }
00229
00230 return (fopen_comp(tmpfile, "r", ispipe));
00231 #endif
00232 }
00233
00234 lineiter_t *
00235 lineiter_start(FILE *fh)
00236 {
00237 lineiter_t *li;
00238
00239 li = ckd_calloc(1, sizeof(*li));
00240 li->buf = ckd_malloc(128);
00241 li->buf[0] = '\0';
00242 li->bsiz = 128;
00243 li->len = 0;
00244 li->fh = fh;
00245
00246 return lineiter_next(li);
00247 }
00248
00249 lineiter_t *
00250 lineiter_next(lineiter_t *li)
00251 {
00252
00253 if (fgets(li->buf, li->bsiz, li->fh) == NULL) {
00254 lineiter_free(li);
00255 return NULL;
00256 }
00257
00258
00259 li->len = strlen(li->buf);
00260 if (li->len < li->bsiz - 1 || li->buf[li->len - 1] == '\n')
00261 return li;
00262
00263
00264 while (1) {
00265 li->bsiz *= 2;
00266 li->buf = ckd_realloc(li->buf, li->bsiz);
00267
00268 if (fgets(li->buf + li->len, li->bsiz - li->len, li->fh) == NULL) {
00269 li->len += strlen(li->buf + li->len);
00270 return li;
00271 }
00272 li->len += strlen(li->buf + li->len);
00273
00274 if (li->len < li->bsiz - 1 || li->buf[li->len - 1] == '\n')
00275 return li;
00276 }
00277
00278
00279 return li;
00280 }
00281
00282 void
00283 lineiter_free(lineiter_t *li)
00284 {
00285 ckd_free(li->buf);
00286 ckd_free(li);
00287 }
00288
00289 char *
00290 fread_line(FILE *stream, size_t *out_len)
00291 {
00292 char *output, *outptr;
00293 char buf[128];
00294
00295 output = outptr = NULL;
00296 while (fgets(buf, sizeof(buf), stream)) {
00297 size_t len = strlen(buf);
00298
00299 if (output == NULL) {
00300 output = ckd_malloc(len + 1);
00301 outptr = output;
00302 }
00303 else {
00304 size_t cur = outptr - output;
00305 output = ckd_realloc(output, cur + len + 1);
00306 outptr = output + cur;
00307 }
00308 memcpy(outptr, buf, len + 1);
00309 outptr += len;
00310
00311 if (len < sizeof(buf)-1 || buf[len-1] == '\n')
00312 break;
00313 }
00314 if (out_len) *out_len = outptr - output;
00315 return output;
00316 }
00317
00318
00319 #define FREAD_RETRY_COUNT 60
00320
00321 int32
00322 fread_retry(void *pointer, int32 size, int32 num_items, FILE * stream)
00323 {
00324 char *data;
00325 uint32 n_items_read;
00326 uint32 n_items_rem;
00327 uint32 n_retry_rem;
00328 int32 loc;
00329
00330 n_retry_rem = FREAD_RETRY_COUNT;
00331
00332 data = pointer;
00333 loc = 0;
00334 n_items_rem = num_items;
00335
00336 do {
00337 n_items_read = fread(&data[loc], size, n_items_rem, stream);
00338
00339 n_items_rem -= n_items_read;
00340
00341 if (n_items_rem > 0) {
00342
00343
00344 if (n_retry_rem == 0)
00345 return -1;
00346
00347 if (n_retry_rem == FREAD_RETRY_COUNT) {
00348 E_ERROR_SYSTEM("fread() failed; retrying...\n");
00349 }
00350
00351 --n_retry_rem;
00352
00353 loc += n_items_read * size;
00354 #ifdef HAVE_UNISTD_H
00355 sleep(1);
00356 #endif
00357 }
00358 } while (n_items_rem > 0);
00359
00360 return num_items;
00361 }
00362
00363
00364 #ifdef _WIN32_WCE
00365 int32
00366 stat_retry(const char *file, struct stat * statbuf)
00367 {
00368 WIN32_FIND_DATA file_data;
00369 HANDLE *h;
00370 wchar_t *wfile;
00371 size_t len;
00372
00373 len = mbstowcs(NULL, file, 0) + 1;
00374 wfile = ckd_calloc(len, sizeof(*wfile));
00375 mbstowcs(wfile, file, len);
00376 if ((h = FindFirstFile(wfile, &file_data)) == INVALID_HANDLE_VALUE) {
00377 ckd_free(wfile);
00378 return -1;
00379 }
00380 ckd_free(wfile);
00381 memset(statbuf, 0, sizeof(statbuf));
00382 statbuf->st_mtime = file_data.ftLastWriteTime.dwLowDateTime;
00383 statbuf->st_size = file_data.nFileSizeLow;
00384 FindClose(h);
00385
00386 return 0;
00387 }
00388
00389
00390 int32
00391 stat_mtime(const char *file)
00392 {
00393 struct stat statbuf;
00394
00395 if (stat_retry(file, &statbuf) != 0)
00396 return -1;
00397
00398 return ((int32) statbuf.st_mtime);
00399 }
00400 #else
00401 #define STAT_RETRY_COUNT 10
00402 int32
00403 stat_retry(const char *file, struct stat * statbuf)
00404 {
00405 int32 i;
00406
00407
00408
00409 for (i = 0; i < STAT_RETRY_COUNT; i++) {
00410
00411 #ifndef HAVE_SYS_STAT_H
00412 FILE *fp;
00413
00414 if ((fp=(FILE *)fopen(file, "r"))!= 0)
00415 {
00416 fseek( fp, 0, SEEK_END);
00417 statbuf->st_size = ftell( fp );
00418 fclose(fp);
00419 return 0;
00420 }
00421
00422 #else
00423 if (stat(file, statbuf) == 0)
00424 return 0;
00425 #endif
00426 if (i == 0) {
00427 E_ERROR_SYSTEM("stat(%s) failed; retrying...\n", file);
00428 }
00429 #ifdef HAVE_UNISTD_H
00430 sleep(1);
00431 #endif
00432 }
00433
00434 return -1;
00435 }
00436
00437 int32
00438 stat_mtime(const char *file)
00439 {
00440 struct stat statbuf;
00441
00442 #ifdef HAVE_SYS_STAT_H
00443 if (stat(file, &statbuf) != 0)
00444 return -1;
00445 #else
00446 if (stat_retry(file, &statbuf) != 0)
00447 return -1;
00448 #endif
00449
00450 return ((int32) statbuf.st_mtime);
00451 }
00452 #endif