|
|
1.1 root 1: /* 1.1.1.2 ! root 2: Hatari - zip.c ! 3: ! 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. 1.1 root 6: 7: Zipped disc support, uses zlib 8: */ 1.1.1.2 ! root 9: char ZIP_rcsid[] = "Hatari $Id: zip.c,v 1.9 2004/05/03 15:34:50 thothy Exp $"; 1.1 root 10: 11: #include <stdio.h> 12: #include <stdlib.h> 13: #include <string.h> 14: #include <unistd.h> 15: #include <dirent.h> 16: 1.1.1.2 ! root 17: #include <zlib.h> ! 18: 1.1 root 19: #include "main.h" 1.1.1.2 ! root 20: #include "dim.h" 1.1 root 21: #include "errlog.h" 1.1.1.2 ! root 22: #include "file.h" ! 23: #include "floppy.h" ! 24: #include "memAlloc.h" ! 25: #include "msa.h" ! 26: #include "st.h" 1.1 root 27: #include "unzip.h" 28: #include "zip.h" 29: 30: /* #define SAVE_TO_ZIP_IMAGES */ 31: 32: #define ZIP_PATH_MAX 256 33: 34: #define ZIP_FILE_ST 1 35: #define ZIP_FILE_MSA 2 1.1.1.2 ! root 36: #define ZIP_FILE_DIM 3 ! 37: ! 38: ! 39: /*-----------------------------------------------------------------------*/ ! 40: /* ! 41: Does filename end with a .ZIP extension? If so, return TRUE ! 42: */ ! 43: BOOL ZIP_FileNameIsZIP(char *pszFileName) ! 44: { ! 45: return(File_DoesFileExtensionMatch(pszFileName,".zip")); ! 46: } 1.1 root 47: 48: 1.1.1.2 ! root 49: /*-----------------------------------------------------------------------*/ ! 50: /* ! 51: Check if a file name contains a slash or backslash and return its position. ! 52: */ ! 53: static int Zip_FileNameHasSlash(char *fn) 1.1 root 54: { 55: int i=0; 56: while( fn[i] != '\0' ) 57: { 58: if( fn[i] == '\\' || fn[i] == '/') return( i ); 59: i++; 60: } 61: return( -1 ); 62: } 63: 1.1.1.2 ! root 64: 1.1 root 65: /*-----------------------------------------------------------------------*/ 66: /* 67: Returns a list of files from a zip file. returns NULL on failure, 68: returns a pointer to an array of strings if successful. Sets nfiles 69: to the number of files. 70: */ 71: zip_dir *ZIP_GetFiles(char *pszFileName) 72: { 73: int nfiles; 1.1.1.2 ! root 74: unsigned int i; 1.1 root 75: unz_global_info gi; 76: int err; 77: unzFile uf; 78: char **filelist; 79: unz_file_info file_info; 80: char filename_inzip[ZIP_PATH_MAX]; 81: zip_dir *zd; 82: 83: uf = unzOpen(pszFileName); 84: if (uf==NULL) 85: { 86: printf("Cannot open %s\n", pszFileName); 87: return(0); 88: } 89: 90: err = unzGetGlobalInfo (uf,&gi); 91: if (err!=UNZ_OK){ 92: printf("error %d with zipfile in unzGetGlobalInfo \n",err); 93: return(NULL); 94: } 95: 96: /* allocate a file list */ 97: filelist = (char **)Memory_Alloc(gi.number_entry*sizeof(char *)); 98: nfiles = gi.number_entry; /* set the number of files */ 99: 100: for(i=0;i<gi.number_entry;i++) 101: { 102: err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip, ZIP_PATH_MAX,NULL,0,NULL,0); 103: if (err!=UNZ_OK) 104: { 105: Memory_Free(filelist); 106: return(NULL); 107: } 108: filelist[i] = (char *)Memory_Alloc(strlen(filename_inzip) + 1); 109: strcpy(filelist[i], filename_inzip); 110: if ((i+1)<gi.number_entry) 111: { 112: err = unzGoToNextFile(uf); 113: if (err!=UNZ_OK) 114: { 115: ErrLog_File("ERROR ZIP_GetFiles with zipfile\n"); 116: /* deallocate memory */ 117: for(;i>0;i--)Memory_Free(filelist[i]); 118: Memory_Free(filelist); 119: return(NULL); 120: } 121: } 122: } 123: 1.1.1.2 ! root 124: unzClose(uf); ! 125: 1.1 root 126: zd = (zip_dir *)Memory_Alloc(sizeof(zip_dir)); 127: zd->names = filelist; 128: zd->nfiles = nfiles; 129: return( zd ); 130: } 131: 1.1.1.2 ! root 132: ! 133: /*-----------------------------------------------------------------------*/ ! 134: /* ! 135: Free the memory that has been allocated for a zip_dir. ! 136: */ ! 137: void ZIP_FreeZipDir(zip_dir *f_zd) ! 138: { ! 139: while (f_zd->nfiles > 0) ! 140: { ! 141: f_zd->nfiles--; ! 142: Memory_Free(f_zd->names[f_zd->nfiles]); ! 143: f_zd->names[f_zd->nfiles] = NULL; ! 144: } ! 145: Memory_Free(f_zd->names); ! 146: f_zd->names = NULL; ! 147: Memory_Free(f_zd); ! 148: } ! 149: ! 150: 1.1 root 151: /*-----------------------------------------------------------------------*/ 152: /* 153: Returns a list of files from the directory (dir) in a zip file list (zip) 154: sets entries to the number of entries and returns a dirent structure, or 155: NULL on failure. NOTE: only f_name is set in the dirent structures. 156: */ 157: struct dirent **ZIP_GetFilesDir(zip_dir *zip, char *dir, int *entries) 158: { 159: int i,j; 160: zip_dir *files; 161: char *temp; 162: BOOL flag; 163: int slash; 164: struct dirent **fentries; 165: 166: files = (zip_dir *)Memory_Alloc(sizeof(zip_dir)); 1.1.1.2 ! root 167: files->names = (char **)Memory_Alloc((zip->nfiles + 1) * sizeof(char *)); 1.1 root 168: 169: /* add ".." directory */ 170: files->nfiles = 1; 171: temp = (char *)Memory_Alloc(4); 172: temp[0] = temp[1] = '.'; 173: temp[2] = '/'; temp[3] = '\0'; 174: files->names[0] = temp; 175: 176: for(i=0;i<zip->nfiles;i++) 177: { 178: if(strlen(zip->names[i]) > strlen(dir)) 179: { 180: if(strncasecmp(zip->names[i], dir, strlen(dir)) == 0) 181: { 182: temp = zip->names[i]; 183: temp = (char *)(temp + strlen(dir)); 184: if( temp[0] != '\0') 185: { 186: if( (slash=Zip_FileNameHasSlash(temp)) > 0) 187: { 188: /* file is in a subdirectory, add this subdirectory if it doesn't exist in the list */ 189: flag = FALSE; 190: for(j = files->nfiles-1;j>0;j--) 191: if(strncasecmp(temp, files->names[j], slash+1) == 0) 192: flag=TRUE; 193: if( flag == FALSE ) 194: { 195: files->names[files->nfiles] = (char *)Memory_Alloc(slash+1); 196: strncpy(files->names[files->nfiles], temp, slash+1); 197: ((char *)files->names[files->nfiles])[slash+1] = '\0'; 198: files->nfiles++; 199: } 200: } 201: else 202: { 203: /* add a filename */ 204: files->names[files->nfiles] = (char *)Memory_Alloc(strlen(temp)+1); 205: strncpy(files->names[files->nfiles], temp, strlen(temp)); 206: ((char *)files->names[files->nfiles])[strlen(temp)] = '\0'; 207: files->nfiles++; 208: } 209: } 210: } 211: } 212: } 213: 214: /* copy to a dirent structure */ 215: *entries = files->nfiles; 216: fentries = (struct dirent **)Memory_Alloc(sizeof(struct dirent *)*files->nfiles); 217: for(i=0; i<files->nfiles; i++) 218: { 219: fentries[i] = (struct dirent *)Memory_Alloc(sizeof(struct dirent)); 220: strcpy(fentries[i]->d_name, files->names[i]); 221: } 1.1.1.2 ! root 222: ZIP_FreeZipDir(files); 1.1 root 223: return(fentries); 224: } 225: 226: /*-----------------------------------------------------------------------*/ 227: /* 228: Check an image file in the archive, return the uncompressed length 229: */ 1.1.1.2 ! root 230: static long ZIP_CheckImageFile(unzFile uf, char *filename, int *pDiscType) 1.1 root 231: { 232: unz_file_info file_info; 233: 234: if (unzLocateFile(uf,filename, 0)!=UNZ_OK) 235: { 236: fprintf(stderr, "Error: File \"%s\"not found in the archive!", filename); 237: return(-1); 238: } 239: 240: if( unzGetCurrentFileInfo(uf,&file_info,filename, ZIP_PATH_MAX,NULL,0,NULL,0) != UNZ_OK) 241: { 242: fprintf(stderr, "Error with zipfile in unzGetCurrentFileInfo \n"); 243: return(-1); 244: } 245: 246: /* check for a .msa or .st extention */ 1.1.1.2 ! root 247: if(MSA_FileNameIsMSA(filename, FALSE)) 1.1 root 248: { 1.1.1.2 ! root 249: *pDiscType = ZIP_FILE_MSA; 1.1 root 250: return( file_info.uncompressed_size ); 251: } 252: 1.1.1.2 ! root 253: if(ST_FileNameIsST(filename, FALSE)) 1.1 root 254: { 1.1.1.2 ! root 255: *pDiscType = ZIP_FILE_ST; 1.1 root 256: return( file_info.uncompressed_size ); 257: } 258: 1.1.1.2 ! root 259: if (DIM_FileNameIsDIM(filename, FALSE)) ! 260: { ! 261: *pDiscType = ZIP_FILE_DIM; ! 262: return( file_info.uncompressed_size ); ! 263: } ! 264: ! 265: fprintf(stderr, "Not an .ST, .MSA or .DIM file.\n"); 1.1 root 266: return(0); 267: } 268: 269: /*-----------------------------------------------------------------------*/ 270: /* 1.1.1.2 ! root 271: Return the first .st, .msa or .dim file in a zip, or NULL on failure 1.1 root 272: */ 1.1.1.2 ! root 273: static char *ZIP_FirstFile(char *filename) 1.1 root 274: { 275: zip_dir *files; 276: int i; 277: char *name; 278: 279: if((files = ZIP_GetFiles(filename)) == NULL) return(NULL); 280: name = Memory_Alloc(ZIP_PATH_MAX); 281: 282: name[0] = '\0'; 283: for(i=files->nfiles-1;i>=0;i--) 1.1.1.2 ! root 284: { ! 285: if (MSA_FileNameIsMSA(files->names[i], FALSE) ! 286: || ST_FileNameIsST(files->names[i], FALSE) ! 287: || DIM_FileNameIsDIM(files->names[i], FALSE)) 1.1 root 288: strncpy(name, files->names[i], ZIP_PATH_MAX); 1.1.1.2 ! root 289: } ! 290: 1.1 root 291: /* free the files */ 1.1.1.2 ! root 292: ZIP_FreeZipDir(files); 1.1 root 293: 294: if(name[0] == '\0') 295: return(NULL); 296: return(name); 297: } 298: 299: 300: /*-----------------------------------------------------------------------*/ 301: /* 302: Extract a file (filename) from a ZIP-file (uf), the number of 303: bytes to uncompress is size. Returns a pointer to a buffer containing 304: the uncompressed data, or NULL. 305: */ 1.1.1.2 ! root 306: static char *ZIP_ExtractFile(unzFile uf, char *filename, uLong size) 1.1 root 307: { 308: int err = UNZ_OK; 309: char filename_inzip[ZIP_PATH_MAX]; 310: void* buf; 311: uInt size_buf; 312: unz_file_info file_info; 313: 314: 315: if (unzLocateFile(uf,filename, 0)!=UNZ_OK) 316: { 317: fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n"); 318: ErrLog_File("ERROR ZIP_ExtractFile could not find file in archive\n"); 319: return NULL; 320: } 321: 322: err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); 323: 324: if (err!=UNZ_OK) 325: { 326: fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n"); 327: ErrLog_File("ERROR ZIP_ExtractFile could not get file info\n"); 328: return NULL; 329: } 330: 331: size_buf = size; 332: buf = Memory_Alloc(size_buf); 333: 334: err = unzOpenCurrentFile(uf); 335: if (err!=UNZ_OK) 336: { 337: fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n"); 338: ErrLog_File("ERROR ZIP_ExtractFile could not open file\n"); 339: return(NULL); 340: } 341: 342: do 343: { 344: err = unzReadCurrentFile(uf,buf,size_buf); 345: if (err<0) 346: { 347: fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n"); 348: ErrLog_File("ERROR ZIP_ExtractFile could not read file\n"); 349: return(NULL); 350: } 351: } while (err>0); 352: 353: return buf; 354: } 355: 356: /*-----------------------------------------------------------------------*/ 357: /* 358: Load .ZIP file into memory, return number of bytes loaded 359: 360: */ 1.1.1.2 ! root 361: Uint8 *ZIP_ReadDisc(char *pszFileName, char *pszZipPath, long *pImageSize) 1.1 root 362: { 363: uLong ImageSize=0; 364: unzFile uf=NULL; 1.1.1.2 ! root 365: Uint8 *buf; ! 366: int nDiscType; 1.1 root 367: BOOL pathAllocated=FALSE; 1.1.1.2 ! root 368: Uint8 *pDiscBuffer = NULL; ! 369: ! 370: *pImageSize = 0; 1.1 root 371: 372: uf = unzOpen(pszFileName); 373: if (uf==NULL) 374: { 375: printf("Cannot open %s\n", pszFileName); 1.1.1.2 ! root 376: return NULL; 1.1 root 377: } 378: 379: if (pszZipPath == NULL || pszZipPath[0] == 0) 380: { 381: if((pszZipPath = ZIP_FirstFile(pszFileName)) == NULL) 382: { 383: printf("Cannot open %s\n", pszFileName); 1.1.1.2 ! root 384: unzClose(uf); ! 385: return NULL; 1.1 root 386: } 387: pathAllocated=TRUE; 388: } 389: 1.1.1.2 ! root 390: if((ImageSize = ZIP_CheckImageFile(uf, pszZipPath, &nDiscType)) <= 0) 1.1 root 391: { 1.1.1.2 ! root 392: unzClose(uf); ! 393: return NULL; 1.1 root 394: } 395: 396: /* extract to buf */ 397: buf=ZIP_ExtractFile(uf, pszZipPath, ImageSize); 398: unzCloseCurrentFile(uf); 1.1.1.2 ! root 399: unzClose(uf); 1.1 root 400: if(buf == NULL) 401: { 1.1.1.2 ! root 402: return NULL; /* failed extraction, return error */ 1.1 root 403: } 404: 1.1.1.2 ! root 405: if (nDiscType == ZIP_FILE_ST) ! 406: { ! 407: /* ST image => return buffer directly */ ! 408: pDiscBuffer = buf; ! 409: } ! 410: else if (nDiscType == ZIP_FILE_MSA) 1.1 root 411: { 412: /* uncompress the MSA file */ 1.1.1.2 ! root 413: pDiscBuffer = MSA_UnCompress(buf, &ImageSize); 1.1 root 414: } 1.1.1.2 ! root 415: else if (nDiscType == ZIP_FILE_DIM) ! 416: { ! 417: /* Skip DIM header */ ! 418: ImageSize -= 32; ! 419: pDiscBuffer = malloc(ImageSize); ! 420: if (pDiscBuffer) ! 421: memcpy(pDiscBuffer, buf+32, ImageSize); ! 422: else ! 423: perror("ZIP_ReadDisc"); ! 424: } ! 425: ! 426: /* Free the buffers */ ! 427: if (pDiscBuffer != buf) ! 428: Memory_Free(buf); 1.1 root 429: if(pathAllocated == TRUE) 430: Memory_Free(pszZipPath); 431: 1.1.1.2 ! root 432: if (pDiscBuffer != NULL) ! 433: *pImageSize = ImageSize; ! 434: ! 435: return(pDiscBuffer); 1.1 root 436: } 437: 438: 439: /*-----------------------------------------------------------------------*/ 440: /* 441: Save .ZIP file from memory buffer. Returns TRUE is all OK 442: 443: Not yet implemented. 444: */ 445: BOOL ZIP_WriteDisc(char *pszFileName,unsigned char *pBuffer,int ImageSize) 446: { 447: return(FALSE); 448: } 449:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.