/** * @file cab.c Microsoft Cabinet module * * $Id: cab.c,v 1.7 2003/01/01 06:22:31 chipx86 Exp $ * * @Copyright (C) 1999-2003 The GNUpdate Project. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "cab.h" #if 0 static size_t __readFunc(void *ptr, size_t size, size_t nmemb, CxFP *fp) { return 0; } static size_t __writeFunc(const void *ptr, size_t size, size_t nmemb, CxFP *fp) { return 0; } static void __seekFunc(CxFP *fp, long offset, int whence) { } static void __closeFunc(CxFP *fp) { } #endif static CxStatus processCab(const char *basePath, const char *filename, CxArchive *archive, CabModuleData *data, CabInfo **destInfo) { CabInfo *info; CxFP *fp; char *path; size_t pathSize; pathSize = strlen(basePath) + strlen(filename) + 2; MEM_CHECK(path = (char *)malloc(pathSize)); snprintf(path, pathSize, "%s/%s", basePath, filename); fp = cxOpenFile(path, CX_MODE_READ_ONLY | CX_MODE_RAW); if (fp != NULL) { cxCabReadInfo(archive, &info, fp); /* Add to the list. */ if (data->cabFiles == NULL) data->cabFiles = info; info->prev = data->lastCabFile; if (data->lastCabFile != NULL) data->lastCabFile->next = info; data->lastCabFile = info; } free(path); *destInfo = info; return CX_SUCCESS; } static CxStatus readArchive(CxArchive *archive, CxFP *fp) { CxDirectory *root; CabModuleData *data; CabHeader *header; CabInfo *info; CxStatus status; MEM_CHECK(data = (CabModuleData *)malloc(sizeof(CabModuleData))); memset(data, 0, sizeof(CabModuleData)); root = cxGetArchiveRoot(archive); if ((status = cxCabReadInfo(archive, &info, fp)) != CX_SUCCESS) return status; header = &info->u.header; data->cabFiles = info; if (CAB_HAS_PREV(header) || CAB_HAS_NEXT(header)) { size_t cabNum; char *basePath; CabInfo *archInfo; int i; cabNum = header->cabNum; archInfo = info; /* Get the base path of the cabinet. */ basePath = cxGetBasePath(cxGetArchivePath(archive)); /* Now get the previous archive. */ for (i = 0; i < cabNum; i++) { if ((status = processCab(basePath, archInfo->prevFile, archive, data, &archInfo)) != CX_SUCCESS) { return status; } } archInfo = info; /* Now get the next archive. */ while (archInfo->nextFile != NULL) { if ((status = processCab(basePath, archInfo->nextFile, archive, data, &archInfo)) != CX_SUCCESS) { return status; } } free(basePath); } return CX_SUCCESS; } static CxStatus saveArchive(CxArchive *archive, CxFP *fp) { return CX_NOT_SUPPORTED; } static void closeArchive(CxArchive *archive) { archive->moduleData = NULL; } static CxFP * openFile(CxFile *file, CxAccessMode mode) { return NULL; } static void destroyFile(CxFile *file) { file->moduleData = NULL; } static char supportsExtension(const char *ext) { if (!strcasecmp(ext, "cab")) return 1; return 0; } static CxArchiveOps ops = { readArchive, /* openArchive */ saveArchive, /* saveArchive */ closeArchive, /* closeArchive */ openFile, /* openFile */ destroyFile, /* destroyFile */ supportsExtension /* supportsExtension */ }; static void __moduleInit(CxModuleType type) { } CX_INIT_ARCHIVE_MODULE(cab, __moduleInit, ops)