#include #include #include "openfiles.h" #include "libs.h" static openfile_t *find_file_by_name(openfiles_t *of, const char *name, int alloc, const char *mode, int recursion) { int n; struct stat buf; FILE *f; if (recursion > 4) { fprintf(stderr, "scconfig internal error: openfiles infinite recursion for %s\n", name); abort(); } if (stat(name, &buf) != 0) { /* File does not exist - try to create it or return NULL */ if (*mode == 'w') { f = fopen(name, "w"); if (f == NULL) return NULL; fclose(f); return find_file_by_name(of, name, alloc, mode, recursion + 1); } return NULL; } /* look for an existing open file in the list */ for(n = 0; n < of->used; n++) if ((of->files[n].dev == buf.st_dev) && (of->files[n].ino == buf.st_ino) && (strcmp(of->files[n].mode, mode) == 0)) return &(of->files[n]); if (!alloc) return NULL; /* File exists but not on the list yet, allocate a new slot for it */ /* TODO: try to find an empty slot first */ if (of->used >= of->alloced) { of->alloced += 16; of->files = realloc(of->files, sizeof(openfile_t) * of->alloced); } n = of->used; of->files[n].dev = buf.st_dev; of->files[n].ino = buf.st_ino; of->files[n].f = NULL; of->files[n].mode = strclone(mode); of->used++; return &(of->files[n]); } void release(openfile_t *o) { if (o->mode != NULL) { free(o->mode); o->mode = NULL; } if (o->f != NULL) { fclose(o->f); o->f = NULL; } o->dev = -1; o->ino = -1; } FILE *openfile_open(openfiles_t *of, const char *fn, const char *mode) { openfile_t *o; o = find_file_by_name(of, fn, 1, mode, 0); if (o == NULL) return NULL; o->f = fopen(fn, mode); if (o->f == NULL) { release(o); return NULL; } return o->f; } void openfile_closeall(openfiles_t *of) { int n; if (of->files == NULL) return; for(n = 0; n < of->used; n++) release(&(of->files[n])); } void openfile_free(openfiles_t *of) { openfile_closeall(of); if (of->files != NULL) free(of->files); }