/* * archive.c -- enfle transparent archive file handler * (C)Copyright 1998, 99 by Hiroshi Takekawa * This file if part of Enfle. * * Last Modified: Mon Mar 6 04:00:45 2000. * $Id: archive.c,v 1.8 2000/03/22 18:09:13 sian Exp $ * * Enfle is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Enfle is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include "archive.h" #include "plugin.h" static Dlist *plugin_list = NULL; static Archive * archive_open_core(Dlist *p, Archive *ar) { Dlist_data *t; PluginInfo *pinfo, *gz_pinfo = NULL, *bz2_pinfo = NULL; int if_stdin = !strcmp(ar->filename, "-"); if (!if_stdin) { for (t = dlist_gettop(p); t != NULL; t = t->next) { pinfo = t->data; ar->fp = NULL; if (pinfo->type == _Archiver) { if (!strcmp(pinfo->pluginshortname, "GZ")) { gz_pinfo = pinfo; continue; } else if (!strcmp(pinfo->pluginshortname, "BZ2")) { bz2_pinfo = pinfo; continue; } else if ((*pinfo->functions.archiver.open)(ar)) return ar; } } if (gz_pinfo && (*gz_pinfo->functions.archiver.open)(ar)) return ar; if (bz2_pinfo && (*bz2_pinfo->functions.archiver.open)(ar)) return ar; } /* normal file */ if (!if_stdin) { if ((ar->fp = fopen(ar->filename, "rb")) == NULL) { free(ar); return NULL; } } else { int size; unsigned char buf[1024]; #if HAVE_MKSTEMP int fd; char *tmpfilename; if ((tmpfilename = calloc(strlen("/tmp/.enfle.XXXXXX") + 1, sizeof(char))) == NULL) { fprintf(stderr, "archive_open_core: no enough memory.\n"); exit(1); } strcpy(tmpfilename, "/tmp/.enfle.XXXXXX"); if ((fd = mkstemp(tmpfilename)) == -1) { perror("enfle: mkstemp:"); fprintf(stderr, "archive_open_core: cannot create tmp file.\n"); exit(1); } if (unlink(tmpfilename)) { perror("archive_open_core: unlink: "); exit(1); } free(tmpfilename); if ((ar->fp = fdopen(fd, "w+b")) == NULL) { fprintf(stderr, "archive_open_core: cannot open created tmp file.\n"); exit(1); } #else if ((ar->fp = tmpfile()) == NULL) { fprintf(stderr, "archive_open_core: cannot open tmp file.\n"); exit(1); } #endif while ((size = fread(buf, 1, 1024, stdin))) fwrite(buf, 1, size, ar->fp); } fseek(ar->fp, 0L, SEEK_END); ar->asize = ar->size = ftell(ar->fp); fseek(ar->fp, 0L, SEEK_SET); ar->offset = 0; #ifdef DEBUG fprintf(stderr, "opening as normal file: size = %d\n", ar->size); #endif ar->format = "NOR"; ar->nfiles = 1; ar->select = NULL; ar->seek = NULL; ar->tell = NULL; ar->read = NULL; ar->close = NULL; return ar; } Archive * archive_open(Dlist *p, char *filename) { Archive *ar; plugin_list = p; if ((ar = calloc(1, sizeof(Archive))) == NULL) return NULL; ar->filename = filename; return archive_open_core(p, ar); } Archive * archive_open_from_plugin(char *filename, char *format) { Archive *ar; if ((ar = calloc(1, sizeof(Archive))) == NULL) return NULL; ar->filename = filename; ar->format = format; return archive_open_core(plugin_list, ar); } int archive_select(Archive *ar, int index) { if (ar->select != NULL) return (ar->select)(ar, index); ar->index = index; return 1; } int archive_seek(Archive *ar, long pos, int whence) { if (ar->seek != NULL) return (ar->seek)(ar, pos, whence); switch (whence) { case SEEK_SET: return fseek(ar->fp, ar->offset + pos, SEEK_SET); case SEEK_CUR: return fseek(ar->fp, pos, SEEK_CUR); case SEEK_END: return fseek(ar->fp, ar->offset + ar->size - 1 + pos, SEEK_SET); default: fprintf(stderr, "archive_seek: FATAL: Invalid whence specified: %d\n", whence); exit(-1); } } int archive_tell(Archive *ar) { if (ar->tell != NULL) return (ar->tell)(ar); return ftell(ar->fp) - ar->offset; } int archive_read(Archive *ar, unsigned char *buf, int size) { if (ar->read != NULL) return (ar->read)(ar, buf, size); return fread(buf, 1, size, ar->fp); } int archive_getc(Archive *ar) { unsigned char d; if (archive_read(ar, &d, 1) == 1) return (int)d; return -1; } unsigned char * archive_gets(Archive *ar, unsigned char *buf, int size) { unsigned char *p = buf; int r; for (; size > 1; size--) { if ((r = archive_read(ar, p, 1)) < 0) return NULL; if (r != 1) break; if (*p == '\n' || *p == '\0') { p++; break; } p++; } *p = '\0'; return buf; } int archive_close(Archive *ar) { int f; if (ar->close != NULL) f = (ar->close)(ar); else f = fclose(ar->fp); free(ar); return f; }