/* * dri.c -- dri file handler * (C)Copyright 1998, 99 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Sun Jan 9 14:40:51 2000. * $Id: dri.c,v 1.12 2000/01/23 11:19:11 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 "enfle.h" #include "utils.h" #include "plugin.h" #include "dri.h" /* define if you want to pack mapping table */ #define REMAP 1 int #ifdef PIC get_plugininfo(PluginInfo *p) #else archiver_dri_get_plugininfo(PluginInfo *p) #endif { p->version = 1; p->type = _Archiver; p->pluginname = "DRI Format Archiver Plugin version 0.2.1"; p->pluginshortname = FORMAT_NAME; p->author = "Hiroshi Takekawa"; p->dlhandle = NULL; /* set by plugin_load */ p->functions.archiver.open = dri_archive_open; return 1; } int dri_archive_open(Archive *ar) { DRI_info *info; char buf[6]; int ptrsize, mapsize; int i; if ((ar->fp = fopen(ar->filename, "rb")) == NULL) return 0; #ifdef DEBUG fprintf(stderr, "dri_archive_open(): open %s\n", ar->filename); #endif fseek(ar->fp, 0L, SEEK_END); ar->asize = ftell(ar->fp); fseek(ar->fp, 0L, SEEK_SET); if (fread(buf, 1, 6, ar->fp) != 6) { fclose(ar->fp); return 0; } ptrsize = (((buf[2] << 8) + buf[1]) << 8) + buf[0]; mapsize = (((buf[5] << 8) + buf[4]) << 8) + buf[3] - ptrsize; #ifdef DEBUG fprintf(stderr, "dri_archive_open: ptrsize = %d, mapsize = %d, asize = %d\n", ptrsize, mapsize, ar->asize); #endif if ((mapsize << 8) > ar->asize || (ptrsize << 8) > ar->asize || mapsize < 0 || ptrsize < 0) { #ifdef DEBUG fprintf(stderr, "Invalid mapsize or ptrsize\n"); #endif fclose(ar->fp); return 0; } /* allocate DRI_info */ if ((info = calloc(1, sizeof(DRI_info))) == NULL) { fprintf(stderr, "No enough memory for info\n"); fclose(ar->fp); return 0; } fseek(ar->fp, 0L, SEEK_SET); if ((info->ptr = malloc(ptrsize << 8)) == NULL) { #if DEBUG fprintf(stderr, "No enough memory for ptr\n"); #endif fclose(ar->fp); free(info); return 0; } if (fread(info->ptr, 1, ptrsize << 8, ar->fp) != ptrsize << 8) { #ifdef DEBUG fprintf(stderr, "Error while reading ptr\n"); #endif fclose(ar->fp); free(info->ptr); free(info); return 0; } fseek(ar->fp, ptrsize << 8, SEEK_SET); if ((info->map = malloc(mapsize << 8)) == NULL) { #ifdef DEBUG fprintf(stderr, "No enough memory for map\n"); #endif fclose(ar->fp); free(info->ptr); free(info); return 0; } if (fread(info->map, 1, mapsize << 8, ar->fp) != mapsize << 8) { #ifdef DEBUG fprintf(stderr, "Error while reading map\n"); #endif fclose(ar->fp); free(info->map); free(info->ptr); free(info); return 0; } ar->nfiles = 0; for (i = 0; i < (mapsize << 8) / 3; i++) if (info->map[i * 3]) { #ifdef REMAP info->map[ar->nfiles * 3] = info->map[i * 3]; info->map[ar->nfiles * 3 + 1] = info->map[i * 3 + 1]; info->map[ar->nfiles * 3 + 2] = info->map[i * 3 + 2]; #endif ar->nfiles++; } #ifdef DEBUG fprintf(stderr, "nfiles = %d\n", ar->nfiles); #endif /* sanity check */ { int f_num = info->map[0]; int f_loc = info->map[1] + (info->map[2] << 8); int f_ptr; if (f_loc * 3 + 2 > ptrsize << 8) { #ifdef DEBUG fprintf(stderr, "Sanity check error: f_loc * 3 + 2 > ptrsize << 8\n"); #endif fclose(ar->fp); free(info->map); free(info->ptr); free(info); return 0; } f_ptr = (((info->ptr[f_loc * 3 + 2] << 8) + info->ptr[f_loc * 3 + 1]) << 8) + info->ptr[f_loc * 3]; if (f_num < 0 || f_num > 10 || f_loc < 0 || f_loc > 8192 || f_ptr < 0) { #ifdef DEBUG fprintf(stderr, "Sanity check error: f_num = %d, f_loc = %d, f_ptr = %d\n", f_num, f_loc, f_ptr); #endif fclose(ar->fp); free(info->map); free(info->ptr); free(info); return 0; } } ar->info = info; ar->format = FORMAT_NAME; ar->select = dri_archive_select; ar->seek = NULL; ar->tell = NULL; ar->read = NULL; ar->close = dri_archive_close; return 1; } int dri_archive_select(Archive *ar, int index) { DRI_info *info = ar->info; unsigned char buf[256 + 16]; int f_num = 0, f_loc = 0, f_ptr = 0; long offset; if (index < 0) return 0; f_num = info->map[index * 3]; #ifdef DEBUG fprintf(stderr, "f_num = %d\n", f_num); #endif if (f_num == 0) return 0; f_loc = (info->map[index * 3 + 2] << 8) + info->map[index * 3 + 1]; f_ptr = (((info->ptr[f_loc * 3 + 2] << 8) + info->ptr[f_loc * 3 + 1]) << 8) + info->ptr[f_loc * 3]; #ifdef DEBUG fprintf(stderr, "f_loc = %d, f_ptr = %d\n", f_loc, f_ptr); #endif if (f_num < 0 || f_num > 10 || f_loc < 0 || f_loc > 8192 || f_ptr < 0) return 0; fseek(ar->fp, f_ptr << 8, SEEK_SET); if (fread(buf, 1, 256 + 16, ar->fp) != 256 + 16) return 0; offset = get_little_dword(buf); strncpy(ar->ifname, &buf[16], ((offset - 16) > 16) ? 16 : (offset - 16)); #ifdef DEBUG fprintf(stderr, "name = %s\n", ar->ifname); #endif ar->size = get_little_dword(buf + 4); ar->offset = (f_ptr << 8) + offset; fseek(ar->fp, ar->offset, SEEK_SET); return 1; } int dri_archive_close(Archive *ar) { int f = fclose(ar->fp); DRI_info *info = ar->info; free(info->map); free(info->ptr); free(ar->info); return f; }